Swift URL Session Response gets corrupted when using '&' symbol - ios

I am developing iOS app, I am using URL Session method for make API calls. Api response gives one property which contains AWS s3 link for pdf document.
What should happen:
So in this app, I am retrieving a PDF document from the server to view in the app, so in the GET URL that I'm sending will give a response of an access link of the pdf document generated through AWS S3.
What is happening now:
Document name: Document/sdd3343-sfnf0asdnd0UserB&ServiceLetter.pdf (notice there is an '&' sign)
In the android and Swagger application, this GET URL is working perfect on any circumstances.
but in the iOS version- in the URL session, when ever when there is a '&' sign inside the document's name, the responding access link gets corrupted.
Now in Android and Swagger, when we are accessing the same document, it works perfectly, but for iOS it doesn't.
URL that doesn't work on iOS but that works in Android and Swagger:
https://domainName/api/FileUpload/GetDocumentUrl?S3Key=**Document/sdd3343-sfnf0asdnd0UserB&ServiceLetter.pdf**&fileCategory=2&userId=9888900000
Above url having parameter name called 'S3Key' value is Document/sdd3343 sfnf0asdnd0UserB&ServiceLetter.pdf and it having an ampersand '&' symbol in middle of the name.
iOS response for the above URL:
{"success":true,"response":"https://samplesite.s3.ap-southwest-2.amazonaws.com/Document/sdd3343-sfnf0asdnd0UserB?X-Amz-Expires=3600&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAWEWNDEFIENS88NKWSWIULHKA/20221010/ap-southwest-2/s3/aws4_request&X-Amz-Date=20221010T011135Z&X-Amz-SignedHeaders=host&X-Amz-Signature=44cab95333c0b5e385959835948539845948023823483","error":null}
In here you can see the response which got by the URL Session. But the reponse url body cut off from ampersand symbol.
Current Response: /Document/sdd3343-sfnf0asdnd0UserB?X-Amz-Expires=3600&X.........
Expected Response: /Document/sdd3343-sfnf0asdnd0UserB&ServiceLetter.pdf?X-Amz-Expires=3600&X.........
How to solve this URL Session problem

Note how & characters are used to separate key/value pairs in a URL. Because of this, you cannot have an & in the middle of a value within a URL, because it is interpreted as a delimiter before the next key/value pair. The answer is to percent-escape the & in the value associated with the S3Key key. To do this, the easiest way is URLComponents:
guard var components = URLComponents(string: "https://domainName/api/FileUpload/GetDocumentUrl") else {
print("URLComponents failure")
return
}
components.queryItems = [
URLQueryItem(name: "S3Key", value: "Document/sdd3343-sfnf0asdnd0UserB&ServiceLetter.pdf"),
URLQueryItem(name: "fileCategory", value: "2"),
URLQueryItem(name: "userId", value: "9888900000")
]
guard let url = components.url else {
print("unable to build url")
return
}
print(url) // https://domainName/api/FileUpload/GetDocumentUrl?S3Key=Document/sdd3343-sfnf0asdnd0UserB%26ServiceLetter.pdf&fileCategory=2&userId=9888900000
There are other ways to manually percent-escape the values in the URL, but URLComponents does it reasonably gracefully.

Related

Can not create a Swift URL object including google encrypted polylines

I am having a validation problem creating an URL object in Swift, returning me nil when I attempt to create it by means of this string:
https://maps.googleapis.com/maps/api/staticmap?size=70x70&path=weight:3%7Ccolor:black%7Cenc:oo%60rG%7Bpxm#zHeW%60H%7BDjJPzKwBnKhKzHrVaExa#gWzCeNsO&path=weight:3%7Ccolor:blue%7Cenc:q|_rG%7Dnym#jJPzKwBnKhKzHrV&key=[my api key]
I need to to use Google Maps Static API in order to get an image of the map including a path I pass as argument to the url in the form of an encrypted polyline.
I tried to escape the url using:
addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)
Doing this let me create an URL object, though the polyline is altered and the path won't be drawn.
Could you please give me any suggestion?
PS. If I type the url I get without applying addingPercentEncoding in the browser, it shows me the image as expected.
PPS. GMS SDK was not included in the project by choice
-- EDIT --
Hi, I tried URLComponents solution suggested by Duncan C, though I got the same result with the google encoded path being distorted.
var urlComponents = URLComponents()
urlComponents.scheme = "https"
urlComponents.host = "maps.googleapis.com"
urlComponents.path = "/maps/api/staticmap"
urlComponents.setQueryItems(with: params)
print(urlComponents.url?.absoluteString)
if let url = urlComponents.url { // generates wrong url }
Different parts of a URL need different encoding rules.
I suggest creating your URL using the system class URLComponents. That lets you specify that various parts of a URL (without encoding) and then you query the URLComponents object for the URL.
Edit:
It sounds to me like the problem is in the encoding of your polyline parameters, since you say those are not rendering. You should include a link to the section of the Google documentation on the Google static maps API that deals with encoded polylines, as well as showing your code that encodes your polyline parameters.
A quick Google search on "google maps encoded polyline swift" yielded a project on Github that implements Google's Polyline encoder / decoder in Swift

Create URL with /#/ in path and open in safari

I use firebase dynamic links which contain an URL to our webapp.
If the dynamic link is opened, the deep link is fetched.
So far so good. As we use the /#/path pattern in our webapp to redirect a user to different sections, we have a problem now, creating such an url in our iOS application after we have to append a new parameter in the url
If this example URL is in our dynamic link
https://domain/#/main/page?utm_source=app&utm_medium=button&utm_campaign=testcampaign
i get it and have to append a parameter for autologin mechanism in our webapp.
So here is the point where i fail at two different approaches.
Getting the string from the url and appending the token parameter and value.
This approach works fine until I have to parse the urlString back to an URL object. The /#/ inside causes an error when creating a new URL object.
I try to replace /#/ with /%23/ (encoded #), but this does not work on our ngnix / webapp infrastructure.
Appending the token parameter with new URLQueryItem in URLComponents.
This approach leads to a wrong URL resulting in (token is the added parameter)
https://my-stage.bikersos.com/?token=tokrenvalue#/main/premium?utm_source=app&utm_medium=button&utm_campaign=testcampaign
I append the URL Query Item with this extension
extension URL {
func addQueryParams(newParams: [URLQueryItem]) -> URL? {
let urlComponents = NSURLComponents.init(url: self, resolvingAgainstBaseURL: false)
guard urlComponents != nil else { return nil; }
if (urlComponents?.queryItems == nil) {
urlComponents!.queryItems = []
}
urlComponents!.queryItems!.append(contentsOf: newParams)
print(urlComponents!)
return urlComponents?.url
}
}
does anybody has an idea how I could solve this problem? I personally prefer the second approach, if it is possible to append the parameters at the end
I figured it out how it has to be done with firebase and utm parameters (this link can be added as deep link in a dynamic link for firebase)
https://example.domain.com/?utm_source=newsletter&utm_medium=button&utm_campaign=testcampaign#/path1/subpath?webappparam1=1&webappparam2=asdf
This way all utm parameters are applied and the path will be available in the web application too.
You can add new query params using the iOS SDK but be aware, they are added at the utm parameters location.
If you need to add them at the end, check if there already exists an ? in the path and write your own appending at the end of the url.

http url parameter Invalid Character Error

I have developed a REST API using feathers.js (https://feathersjs.com/).
When trying to do a HTTP 'read' request in Flutter using package:http/http.dart I have encountered an error. The http.dart library is unable to correctly parse the query params I pass to the URI.
The error I receive through the Android Studio debug console is ;
FormatException: Invalid character (at character 84) E/flutter
(11338): ...lk.com/weatherobs?last=true&location[$in]=Bellambi&location[$in]=Nowra ....
The error is indicating the square brackets and possibly the $ sign ('[$in]' ) are the issue.
_getDemoRequest() {
String url = r"http://demoapi.ap-southeast-2.elasticbeanstalk.com/weatherobs?last=true&location[$in]=Bellambi&location[$in]=Nowra&location[$in]=Sydney Airport&location[$in]=Thredbo Top Station&location[$in]=Hobart&location[$in]=Coolangatta";
http.read(url).then(print);
}
In the URL I have tried prefixing the String with and without 'r' for a raw string to no avail.
I have also tried using httpClient with params with no success and the exact same error on the square brackets eg '[$in]'
String httpbaseUri = "http://xxxx.ap-southeast-2.elasticbeanstalk.com";
String qParams = r"?last=true&location[$in]=Bellambi&location[$in]=Nowra";
String path = "/weatherobs";
var _uri = new Uri.http(baseUri, path, qParams);
await httpClient.read(_uri, headers: {"Accept": "application/json"});
As a person with approximately 3 weeks of Flutter/Dart experience I believe its an elementary problem, but one in which several hours of research has uncovered no solution.
The ways the URI query parameters are structured (with the square brackets ie [$in]) are dictated by the feathers.js framework.
Any help would be appreciated.
It has been brought to my attention in another thread https://stackoverflow.com/questions/40568/are-square-brackets-permitted-in-urls :
That the URL Specification RFC 3986 generally does not permit square brackets in an URL.
My question was triggered as the get request works as intended in Postman, Chrome Browser and also javascript applications using axios.js, but not in an application developed in Flutter/Dart using standard http.read methods.
It doesn't look like [] are supported in the URL (except for the host IP for IPv6). See Are square brackets permitted in URLs?.
Please check if the API accepts them when they are encoded like:
void main() {
var url = r'http://demoapi.ap-southeast-2.elasticbeanstalk.com/weatherobs';
var locationKey = Uri.encodeQueryComponent(r'location[$in]');
var qParams = 'last=true&$locationKey=Bellambi&$locationKey=Nowra&$locationKey=Sydney Airport&$locationKey=Thredbo Top Station&$locationKey=Hobart&$locationKey=Coolangatta';
try {
print(Uri.parse(url).replace(query: qParams));
} catch(e) {
print(e);
}
}
DartPad example
See also api.dartlang.org/stable/1.24.3/dart-core/Uri/…
You can use this flutter package which allow you to communicate with your feathers js server from flutter app as said in: https://stackoverflow.com/a/65538226/12461921

Check the validity of a domain name

I need to make sure that a URL that the user inputs goes where it should go. I mean if the user inputs "http://google.com/blablabla" or "http://google123.com/blablabla". I need to figure out that the second url is not correct because it won't open google's web-site. Is there some method in Swift to do that? Or do I just need to check if the URL contains "http://google.com"?
1. Malformed URL
To verify whether or not the URL itself is malformed, let the OS do it:
(check that the URL has all the parts it needs, namely a scheme and a host)
if let url = URL(string: rawStringInput),
let _ = url.scheme,
let _ = url.host {
// rawStringInput is well formed
}
You can then query all sorts of information from the URL, such as scheme (http), the host (google.com), the path (blablabla), fragment, port and so on.
2. Valid URL
If you want to know whether or not the URL is reachable (i.e. the remote server responds to it), you actually need to execute the request.

How make WCF allow dots(.) in url?

I use WCF and have a method like this:
[OperationContract]
[WebInvoke(Method = "GET", UriTemplate = "LoadProducts/{key}/{price}")]
XmlDocument LoadProducts(string key, string price= null);
price is string, inside LoadProducts I will try to parse it from string to double and do my other operations.
But in url, I can not get request any parameter for price like '24.25', '0.253' etc. It does not allow any value with dot.
localhost:13448/RestService.svc/LoadProducts/null/41.145
I get error "Please review the following URL and make sure that it is spelled correctly. "
How can I solve this?
Dots already have a meaning in a URL, they separate the target hostname, IP address or in the path they separate the resources from its extension. You will need to URL encode your request URL.
In .NET there is a method called UrlEncode to help you encode URLs. It is:
string url = "http://localhost/MyService/MyKey/24.25";
string encodedUrl = HttpUtility.UrlEncode(url);
Check out the MSN documentation for UrlEncode for more details.
I solved my issue. I switched server from Visual Studio Development Server to Local IIS Web Server, url took dot symbol inside parameter.

Resources