Get the value of URL Parameters in WKWebView and create new URL - ios

I'm trying to get the current URL of the WKWebView, search/copy one value out of it, and create a new URL.
I use Swift and have this an URL like that https://example.org/bundle-572974a2.html and try to get the following value 572974a2.
My intention is to create a new URL with that value. The numbers can change from time to time.
I use this code to get the current WKWebView URL. I think I have to convert this to a string first.
let oldURL = webView.url
And I use this code to create my new URL.
var components = URLComponents()
components.scheme = "https"
components.host = "new-example.org"
components.path = "/g"
components.queryItems = [
URLQueryItem(name: "newbundle", value: "XXXXXXXX")
]
let newURL = components.url
How can I change/paste the value: "XXXXXXXX" with the value 572974a2 of the old URL?

Some simple URL manipulation and string handling will get you the number from the old URL:
let oldURL = URL(string: "https://example.org/bundle-572974a2.html")! // An example
let name = oldURL.deletingPathExtension().lastPathComponent // bundle-572974a2
let number = name.dropFirst(7) // remove "bundle-"
This assumes the number will always be preceded by "bundle-" (or any seven-letter sequence really. If that can vary then the use of dropFirst(7) will need to be replaced with code that can handle strings like "bundle-572974a2" and remove the part you don't want.
Then building the new URL becomes:
var components = URLComponents()
components.scheme = "https"
components.host = "new-example.org"
components.path = "/g"
components.queryItems = [
URLQueryItem(name: "newbundle", value: String(number))
]
let newURL = components.url
In a case where you might have both a prefix and a suffix you need to remove, the following would be one way to remove them. This code assumes there will be a prefix to remove if there is a suffix to remove. If there is a suffix and no prefix to remove then this code gives the wrong result.
var number = url.deletingPathExtension().lastPathComponent
if let hyphen = number.firstIndex(of: "-") {
number = String(number[number.index(after: hyphen)...])
}
if let hyphen = number.lastIndex(of: "-") {
number = String(number[..<hyphen])
}
P.S. String manipulation in Swift is a pain.

Related

URL is nil or percentage encoded

I have this URL
https://apps.apple.com/developer/john-doe/id32123123#see-all/mac-apps
I do this
let path = "https://apps.apple.com/developer/john-doe/id32123123#see-all/mac-apps"
let url = URL(string: path!)
the resulting url is nil.
I do this:
var components = URLComponents()
components.scheme = "https"
components.host = "apps.apple.com"
components.path = "/developer/john-doe/id32123123#see-all/mac-apps"
let url = components.url!
The resulting url percentage encoded, like this and, as expect, an URLRequest done with that URL fails.
https://apps.apple.com/developer/john-doe/id32123123%23see-all/mac-apps
Is there a way to get a normal URL without any percentage encoding?
How do I do a URL that works with URLRequest?
This code works just fine:
let path = "https://apps.apple.com/developer/john-doe/id32123123#see-all/mac-apps"
let url = URL(string: path)
I just had to remove the !. Path is not optional, so there's nothing to unwrap.
Your latter technique isn't something you should bother using for literal URLs like this, but I can explain why it's "not working" to your expectations anyway. The # marks the beginning of the url's fragment. It's a special character, which is why the system is percent-encoding it for you when you try to use it as part of the path. Here's the fixed code:
var components = URLComponents()
components.scheme = "https"
components.host = "apps.apple.com"
components.path = "/developer/john-doe/id32123123"
components.fragment = "see-all/mac-apps"
let url = components.url! // => "https://apps.apple.com/developer/john-doe/id32123123#see-all/mac-apps"
You should read up on the URL standard.

Swift URL appendingPathComponent converts `?` to `%3F`

let url = URL(string: "https://example.com")
let path = "/somePath?"
let urlWithPath = url?.appendingPathComponent(path)
After appending, the path /somePath? becomes somePath%3F.
The ? becomes a %3F. Question Mark is replaced with the percent-encoded escape characters.
The URL does output correctly if I use:
let urlFormString = URL(string:"https://example.com/somePath?")
Why does appendingPathComponent convert ? to %3F?
How can I use appendingPathComponent if the path component contains a question mark?
The generic format of URL is the following:
scheme:[//[userinfo#]host[:port]]path[?query][#fragment]
The thing you have to realize is that the ? is not part of the path. It is a separator between path and query.
If you try to add ? to path, it must be URL-encoded because ? is not a valid character for a path component.
The best solution would be to drop ? from path. It has no meaning there. However, if you have a partial URL which you want to append to a base URL, then you should join them as strings:
let url = URL(string: "https://example.com")
let path = "/somePath?"
let urlWithPath = url.flatMap { URL(string: $0.absoluteString + path) }
In short, appendingPathComponent is not a function that should be used to append URL query.
You should use removingPercentEncoding on URL's absoluteString,
let url = URL(string: "https://example.com")
let path = "/somePath?"
let urlWithPath = url?.appendingPathComponent(path).absoluteString.removingPercentEncoding
print(urlWithPath!)
%3F stands for ?, according to URL Encoding. So if you create an URL - it has to be that way. If, for some reason, you need your ?, create a string, not URL.
Check urlWithPath.lastPathComponent to see that everything is all right (prints: "somePath?")
First of all it is not a problem. this is a mechanism called URL encoding, for translating unprintable or special characters to a universally accepted format by web servers and browsers.
For more information you can go to https://www.techopedia.com/definition/10346/url-encoding
URL encoded chars, https://www.degraeve.com/reference/urlencoding.php
When you convert the string to URL, It'll be doing PercentEncoding in URL. So that your ? has been encoded into %3F.
If you want the url as string with ?, you can remove the PercentEncoding as like below code.
let urlString = urlWithPath?.absoluteString.removingPercentEncoding
Output: https://example.com/somePath?
Instead of URL can use URLComponents:
var url = URLComponents()
Set the scheme, host and path:
url.scheme = "https"
url.host = "example.com"
url.path = "/somePath"
Set the query as empty string and ? is added since it is a separator between path and query:
url.query = ""
// url.queryItems = [URLQueryItem(name: "nameN", value: "valueX")]
Prints: https://example.com/somePath?
print(url)
You can build your url using NSString class:
let urlStr = "https://example.com" as NSString
let path = "/somePath?"
let urlStrWithPath = urlStr.appendingPathComponent(path)
let url = URL(string: urlStrWithPath)
This way, special characters are not url-encoded in the final url.

Swift 4 How to remove %EF%BB%BF from URL created from URLComponent()?

I attempt to create URL from components
var com = URLComponents()
com.scheme = "http"
com.host = "192.168.1.99"
com.port = 77
com.path = "/api/dosomething/55"
print("SHOW ME URl = \(com.url!))")
What I got is something like this
http://192.168.1.99:77/%EF%BB%BFapi/dosomething/55
Always got %EF%BB%BF, in which case the url becomes invalid
I want to remove %EF%BB%BFfrom the URL
How can I do that?
That's a URL-encoding of a UTF-8 BOM, it may be caused by processing of the URLs with some text editors. Trim white spaces from your path string:
var com = URLComponents()
com.scheme = "http"
com.host = "192.168.1.99"
com.port = 77
let path = //The path
let trimmedPath = path.trimmingCharacters(in: .whitespaces)
com.path = trimmedPath
print("SHOW ME URl = \(com.url!)")
In utf-8, the 'ZERO WIDTH NO-BREAK SPACE' is encoded as 0xEF 0xBB 0xBF
Direct answer to your question
You can replace this pattern with nothing :
let theURL = "http://192.168.1.99:77/%EF%BB%BFapi/dosomething/55"
let partToRemove = "%EF%BB%BF"
let clearURL = theURL.replacingOccurrences(of: partToRemove, with: "")
print(clearURL)

The '#' char gets converted to %23 causing the GET Request to fail

I am a new Swift developer using Swift 3 developing an iOS app. I need to make a URL Request to get some data from the web. That URL contains a # character.
I use URLComponents with URLQueryItems to build the request URL. During this process the # char gets converted to %23 which I think is valid utf8 encoding. Unfortunately, this causes the GET to fail.
To test I pasted the URL into my browser and changed %23 back to # and it worked just fine.
How can I fix this so it does not change # to URL. I did find a post from a couple years ago but it was using old framework items so it does not apply to me.
Below is the playground I made to illustrate and test this.
// ------------------------------------------------------------------
//: Playground - TestBuildURLWithParameters
//
// I am using this playground to build the proper
// URL for the GET request to get the detailed
// rtesults for a specific athlete where the "Key"
// is their Bib Nbr. If the GET cant find the specific
// Atlete with that URL it redirects you to the list
// of athlete results (which is no go to me in this case)
//
// Currently, there is a big "gotcha". In building the URL
// using component and query items, the foundation classes
// replace the '#' sign in the URL with the %23 which represents
// the pound sign. Unfortunately, the causes the GET to fail
// and redirects to athlete list which is not helpful
// I am still trying to figure out how to FORCE it to keep
// the '#" character in the URL so it will work
//
// ------------------------------------------------------------------
import Foundation
import UIKit
let baseURLString = "http://www.ironman.com/triathlon/events/americas/ironman-70.3/augusta/results.aspx"
let rd = "20150927"
let race = "augusta70.3"
let bibID = "93"
var detail = "1#axzz4FGGcjBOn"
print("Detail w/o unicocde: \(detail)")
detail = "1\u{0023}axzz4FGGcjBOn"
print("Detail with unicocde: \(detail)")
var components = URLComponents(string: baseURLString)!
var queryItems: [URLQueryItem] = [] // All Items after the "?"
let baseParams =
[
"rd": rd,
"race": race,
"bidID": bibID, // Note: HTML mispelled bib with bid so "bidID" is the URL search
"detail": detail
]
for (key, value) in baseParams
{
let item = URLQueryItem(name: key, value: value)
queryItems.append(item)
}
components.queryItems = queryItems // what does this look like
print("components: \(components)") // see it
It is not a good way to include fragment part of URL into query items.
Try this:
import Foundation
let baseURLString = "http://www.ironman.com/triathlon/events/americas/ironman-70.3/augusta/results.aspx"
let rd = "20150927"
let race = "augusta70.3"
let bibID = "93"
var detail = "1"
//# split the last query item and the fragment
let fragment = "axzz4FGGcjBOn"
var components = URLComponents(string: baseURLString)!
var queryItems: [URLQueryItem] = []
let baseParams =
[
"rd": rd,
"race": race,
"bidID": bibID,
"detail": detail
]
for (key, value) in baseParams
{
let item = URLQueryItem(name: key, value: value)
queryItems.append(item)
}
components.queryItems = queryItems
components.fragment = fragment
print("components: \(components)")
If you need you can choose the character that will receive the encoding.
In the charactersIn: you put all characters you want to encode.
Then you use the .inverted so all the others characters will go normal like this:
let customAllowedSet = NSCharacterSet(charactersIn:"=\"%/<>?#\\^`{|}").inverted
let encondedString = originalString.addingPercentEncoding(withAllowedCharacters: customAllowedSet)
print("enconded string: \(encondedString)")
Encode your parameters and then add it to URL, this will encode # before hitting API and you'll get desired result.
To encode parameters, you can use below code.
var parameterString = "your parameter string"
var encodedString = parameterString .addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)
print(encodedString !)
I did get an answer via email from a friend that works for now. Basically, I added the query items manually to the URL using the URL extension below so it didn't monkey with the '#' char:
extension URL {
func appendingNonEscapedQueryItems(_ queryItems: [URLQueryItem]) -> URL {
let url = self
var urlString = url.absoluteString
for queryItem in queryItems {
let queryName = queryItem.name
guard let queryValue = queryItem.value else {
continue
}
let query = queryName + "=" + queryValue
if queryItem == queryItems.first {
urlString = urlString + "?" + query
}
else
{
urlString = urlString + "&" + query
}
}
return URL(string: urlString)!
}
}
...
let requestURL = components.url!.appendingNonEscapedQueryItems(queryItems)
print("URL \(requestURL)")

How to send litter '&' as url parameter - swift

I have a code to update name of department in the database .. I use this encoding code :
let myurlstring="http:example/updateDepartment.php?deptName="+"\(deptName)"+"&id="+"\(deptID)"
let escapedString = myurlstring.addingPercentEncoding(withAllowedCharacters:NSCharacterSet.urlQueryAllowed)
let myUrl = URL(string:escapedString!)!
It works very well , but when deptName string contains this litter & it's not working.
example1 : send request with deptName = "CIT and Network" it will work .
example2 : send request with deptName = "CIT & Network" will be in the database as only "CIT" any litter after & will be skipped.
any help ?
Use URLComponents + URLQueryItem instead. It can be used to encode the query part from structured input:
var comp = URLComponents(string: "http://example.com")!
comp.path = "/some path to/update.php"
comp.queryItems = [
URLQueryItem(name: "deptName", value: "CIT & Network"),
URLQueryItem(name: "id", value: "123456"),
]
let url = comp.url!
print(url)
// http://example.com/some%20path%20to/update.php?deptName=CIT%20%26%20Network&id=123456

Resources