0

In order to make HTTP request call using URLSession,I need to convert string to URL first so I have tried everything but just can’t convert this piece of string to URL(string: ). This is the string: “http://api-aws-eu-qa-1.abc-cde.com/v1/car-types/manufacturer?page=0&pageSize=10&wa_key=abc-cde-efg-44ccd99”

I can’t share the exact Url but format is all same. The actual url with same format works fine in browser but no way in Swift, also that works fine in POSTMAN I have also tried URLComponents which hepls me create the URL from components to URL but that fails with 400 status code response error. I really appreciate the help, I am completely bogged down with this isuue and can’t proceed with my assignment.

Update: Tested with fiddler and request was not going through with this URL - "“http://api-aws-eu-qa-1.abc-cde.com%E2%80%8B/v1/car-types/manufacturer?page=0&pageSize=10&wa_key=abc-cde-efg-44ccd99”"

But when removed this %E2%80%8B in fiddler and resend it worked. Any thoughts ..?

gagan sharma
  • 256
  • 1
  • 4
  • 18
  • Have you tried addingPercentEncoding or urlHostAlloqed or urlQuery allowed? – Rob Jan 24 '22 at 15:51
  • If you don't print your api response all you can do is guessing. `print(Data(data: data, encoding: .utf8) ?? "")` – Leo Dabus Jan 24 '22 at 16:08
  • 2
    `URL(string: "http://api-aws-eu-qa-1.abc-cde.com/v1/car-types/manufacturer?page=0&pageSize=10&wa_key=abc-cde-efg-44ccd99")` seems to create an URL without trouble. Do you have an example of a URL that actually fails? – Rob Napier Jan 24 '22 at 16:13
  • I tried addingPercentEncoding with URLQuery, fragments and other ytpes but nothing worked, and when create URL using URLComponents it adds some special characters next to http://api-aws-eu-qa-1.abc-cde.com – gagan sharma Jan 24 '22 at 16:13
  • Check your POSTMAN headers configuration. Are you doing a post or a get? – Leo Dabus Jan 24 '22 at 16:13
  • What special characters does it add next to the host? When I try `URLComponents(string: "http://api-aws-eu-qa-1.abc-cde.com/v1/car-types/manufacturer?page=0&pageSize=10&wa_key=abc-cde-efg-44ccd99")`, it creates an URLComponents without trouble. Can you post code that demonstrates your problem? (You can't just call `addingPercentEncoding` to random parts of a String. It generally is not the right tool unless you know precisely what you're doing.) – Rob Napier Jan 24 '22 at 16:15
  • @LeoDabus I am doing Get and used the Swift code snippet given by postman but that also crashes where URL is forming – gagan sharma Jan 24 '22 at 16:16
  • Are you saying that it is returning `nil` from `URL(string:)` initializer? – Leo Dabus Jan 24 '22 at 16:17
  • What happen when you compose your string using `URLComponents`? – Leo Dabus Jan 24 '22 at 16:17
  • @RobNapier when I use print(urlComponents.url?.absoluteString) it shows this "http://api-aws-eu-qa-1.abc-cde.com%E2%80%8B/v1/car-types/manufacturer?page=0&pageSize=10&wa_key=abc-cde-efg-44ccd99" – gagan sharma Jan 24 '22 at 16:18
  • special characters added by `URLComponents` shouldn't be an issue – Leo Dabus Jan 24 '22 at 16:18
  • 2
    That looks like you called `addingPercentEncoding` blindly on the string. Don't do that. See Euan Traynor's answer for an example of how to use URLComponents. (But I expect the problem is in the specific URL you're trying to encode. You need to show us something that actually fails. I expect your string is just not a legal URL in the first place.) – Rob Napier Jan 24 '22 at 16:19
  • @LeoDabus but in that case request fails with 400 status response but show json response when used in browser – gagan sharma Jan 24 '22 at 16:20
  • As already stated by Rob make sure to pass the string to URLComponents without any percent encoding – Leo Dabus Jan 24 '22 at 16:21
  • @RobNapier but what makes it run fine in safari – gagan sharma Jan 24 '22 at 16:21
  • 2
    @gagansharma it doesnt mean anything. Safari does what you are not doing under the hood. – Leo Dabus Jan 24 '22 at 16:21
  • @LeoDabus I am using URLComponents without any percent encoding – gagan sharma Jan 24 '22 at 16:23
  • 1
    Show your code, how you construct the URL, even if you obfuscate some keys, base URL, etc. But at least try to keep "special characters" if there is... Like `http://myURL.com/path1/path2/query?key1=value_1&key2=value2`, etc. – Larme Jan 24 '22 at 16:51
  • As Leo notes, the Safari address bar accepts a wide variety of strings that are not valid URLs. It has various ad hoc rules for deciding what to do with those strings. The string "example.com" is not a valid URL (it has no scheme), but if you type it into the Safari address bar, it will turn it into `http://example.com` and navigate to it. On the other hand, if I type just "example" (also not an URL), it will convert that to an URL for a web search. You cannot use the Safari address bar to determine if something is an URL. – Rob Napier Jan 24 '22 at 17:02
  • If you cannot show us the specific string that fails, you need to show us *some* string that fails in a similar way. If you just say "I send a string to URL and it doesn't work," the answer is "that string isn't a valid URL." We can't help you beyond that without an example. You can read the rules at [RFC 3986 section 3](https://datatracker.ietf.org/doc/html/rfc3986#section-3) – Rob Napier Jan 24 '22 at 17:04
  • @RobNapier Please see my updated findings in question. – gagan sharma Jan 24 '22 at 18:46
  • "But when removed this %E2%80%8B in fiddler and resend it worked." Yes, because that's not part of a valid HTTP URL. When you connected to a host that didn't exist, it failed. When you edited the URL to connect to a host that does exist, it works. Where did you get this string from? – Rob Napier Jan 24 '22 at 19:32

3 Answers3

1

String to URL

let url = URL(string: "the url string goes here")

URL to String

let url = URL(string: "the url string goes here")
let urlString = url.absoluteString

Creating URL from URLComponents

var url: URL? {
    var components = URLComponents()
    components.scheme = "https"
    components.host = "domain goes here" //example: twitter.com
    components.path = "/path/goes/here"
    components.queryItems = [
        URLQueryItem(name: "item1", value: string1),
        URLQueryItem(name: "item2", value: string2)
    ]

    return components.url
}
Euan Traynor
  • 420
  • 2
  • 11
  • OP have already tried using URLComponents – Leo Dabus Jan 24 '22 at 16:11
  • @LeoDabus It's not clear that the OP has used URLComponents correctly, however (and very likely has not). Demonstrating its use is very helpful. – Rob Napier Jan 24 '22 at 16:17
  • I am already using the same way but it adds %E2%80%8B symbols in Url, then fail – gagan sharma Jan 24 '22 at 18:44
  • You have an invisible character in your URL string. %E2%80%8B refers to the character "Zero Width Space" (Code point: U+200B). Try manually retyping in the URL string completely from scratch... or use the following method. `extension Character { static let zeroWidthSpace = Self(.init(0x200B)!) var isZeroWidthSpace: Bool { self == .zeroWidthSpace } }` and `extension Bool { var negated: Bool { !self }}` and finally call it `let filteredStringURL = str.filter(\.isZeroWidthSpace.negated)` – Euan Traynor Jan 24 '22 at 19:23
0

try to add HEADER to you request:

let url = URL(string : urlString)
var request = URLRequest(url : url)
request.setValue("Application/json", forHTTPHeaderField : "Content-Type")
AdR
  • 572
  • 1
  • 4
  • 13
0

Your URL is:

http://api-aws-eu-qa-1.abc-cde.com%E2%80%8B/v1/car-types/manufacturer?page=0&pageSize=10&wa_key=abc-cde-efg-44ccd99`

The "host" portion is:

api-aws-eu-qa-1.abc-cde.com%E2%80%8B

%E2%80%8B encodes a ZERO WIDTH SPACE. This is a perfectly valid URL:

URL(string: "http://api-aws-eu-qa-1.abc-cde.com%E2%80%8B/v1/car-types/manufacturer?page=0&pageSize=10&wa_key=abc-cde-efg-44ccd99")
=> Optional(http://api-aws-eu-qa-1.abc-cde.com%E2%80%8B/v1/car-types/manufacturer?page=0&pageSize=10&wa_key=abc-cde-efg-44ccd99)

However, there is no such host as api-aws-eu-qa-1.abc-cde.com%E2%80%8B, so you should expect the actual connection to fail.

I expect that whatever is generating your URL strings has a bug.

If you are having trouble creating the URL itself (if URL(string:) return nil, then I expect this is not your actual URL string.

If you construct an URLComponents, the results are correct but may be slightly misleading:

URLComponents(string: "http://api-aws-eu-qa-1.abc-cde.com%E2%80%8B/v1/car-types/manufacturer?page=0&pageSize=10&wa_key=abc-cde-efg-44ccd99")?.host
Optional("api-aws-eu-qa-1.abc-cde.com")

While this looks like "api-aws-eu-qa-1.abc-cde.com", the string actually has a ZERO WIDTH SPACE at the end, which is invisible (but still part of the host field, which will correctly fail if you try to connect to it).

Rob Napier
  • 286,113
  • 34
  • 456
  • 610