Trying to fetch JSON data from an external website for two ISBN numbers and the Curl from that site is shown below. When using the AF.request it works fine for one isbn but when trying the string in the curl request with isbn numbers separated by a common it returns no results. Instead of a comma I have also tried & and &20 and + and nothing seems to work. The website lets you plug in both ISBN numbers and will show you results and gives you the curl statement so I know the curl statement works. Any help is appreciated!
/* curl from ISBNdb
curl -X 'POST' \
'https://api2.isbndb.com/books' \
-H 'accept: application/json' \
-H 'Authorization: mykey' \
-H 'Content-Type: application/json' \
-d 'isbns=9781250178633,9781501110368'
*/
func fetchAPIDataISBN() {
let headers: HTTPHeaders = ["accept": "application/json","Authorization": "mykey","Content-Type": "application/json"]
//let parameters1 = ["isbns": "9781250178633,9781501110368"]
let parameters = ["isbns": "9781250178633"]
AF.request("https://api2.isbndb.com/books", method: .post, parameters: parameters, headers: headers)
I think the problem is mainly on the API being very picky about what it accepts. It seems to accept a URL encoded form with a key isbns
, followed by a comma-separated list of numbers. (Note that this contradicts the Content-Type
header.) So theoretically, declaring parameters
as the following should work
let parameters = ["isbns": "9781250178633,9781501110368"]
However, the API doesn't seem to like this because the comma is percent-encoded as %2C
.
You can force Alamofire to not percent encode the ,
by adding it in the allowedCharacters
set in a URLEncodedFormEncoder
:
AF.request(
"https://api2.isbndb.com/books",
method: .post,
parameters: parameters,
encoder: URLEncodedFormParameterEncoder(encoder: .init(
// feel free to use a larger character set than 'alphanumerics' here if the
// request body has other characters that you don't want to be encoded
allowedCharacters: .alphanumerics.union([","])
)),
headers: headers
)
If you don't need to pass any other parameters, also consider just writing the parameters as a single string:
let parameters = "isbns=9781250178633,9781501110368"
and setting httpBody
directly in the interceptor
parameter:
let request = AF.request(
"https://api2.isbndb.com/books",
method: .post,
headers: headers
) {
$0.httpBody = Data(parameters.utf8)
}