I am trying to send a request to an API from Xcode. I have JWT authentication set up, but when I am adding the Authorization header
with my bearer token
, it is not received on the server. I thought I wasn't doing it right, but my other headers are being sent correctly. I also can make authorization work from postman so i don't think it is my API. I am using the fastAPI framework for my API and Alamofire for making my requests in Swift. Does anyone else have a similar issue or know how to fix it?
This is what my code looks like when I make the request:
func getPosts() {
let headers: HTTPHeaders = [
"Authorization":"Bearer \(UserDefaults.standard.object(forKey: "access_token") as! String)",
"Content-type":"application/json"
]
AF.request("\(mainURL)posts", method: .get, headers: headers).responseDecodable(of: Dictionary<String, String>.self) { response in
debugPrint(response)
}
}
I know my token is being sent correctly because when the debugPrint(response)
is run it spits out this which includes the Authorization header
:
[Request]: GET http://127.0.0.1:8000/posts
[Headers]:
Authorization: Bearer xxxx
Content-Type: application/json
[Body]: None
[Response]:
[Status Code]: 401
[Headers]:
Content-Length: 30
Content-Type: application/json
Date: Fri, 20 Jan 2023 23:27:48 GMT
Server: uvicorn
Www-Authenticate: Bearer
[Body]:
{"detail":"Not authenticated"}
[Network Duration]: 0.13030695915222168s
[Serialization Duration]: 0.0005600140430033207s
[Result]: success(["detail": "Not authenticated"])
However when had my server print out the request headers it gave me this, which is missing the Authorization header
, but the Content-type header
set like it was supposed to:
Headers({'host': '127.0.0.1:8000', 'content-type': 'application/json', 'accept': '*/*', 'user-agent': 'APITest/1.0 (my-Name.APITest; build:1; iOS 16.2.0) Alamofire/5.6.4', 'accept-language': 'en;q=1.0', 'accept-encoding': 'br;q=1.0, gzip;q=0.9, deflate;q=0.8', 'connection': 'keep-alive'})
CodePudding user response:
Ok, I tried your "demo" token and server endpoint, and all is working well for me.
Here is the test code I used. It shows how to fetch, decode and display the data from the server, using your Alamofire code. The important thing here, is that your data models need to match the json data you receive from the server.
Note especially, the last /
in AF.request("\(mainURL)posts/", ...
, that was probably the cause of your error.
import Foundation
import SwiftUI
import Alamofire
// MARK: - ApiResponse
struct ApiResponse: Identifiable, Codable {
let id = UUID()
let post: Post
let votes: Int
enum CodingKeys: String, CodingKey {
case post = "Post"
case votes
}
}
// MARK: - Post
struct Post: Identifiable, Codable {
let title, content: String
let published: Bool
let id, createdAt: String
let ownerID: Int
let owner: Owner
enum CodingKeys: String, CodingKey {
case title, content, published, id
case createdAt = "created_at"
case ownerID = "owner_id"
case owner
}
}
// MARK: - Owner
struct Owner: Identifiable, Codable {
let id, email, createdAt: String
enum CodingKeys: String, CodingKey {
case id, email
case createdAt = "created_at"
}
}
struct ContentView: View {
@State var model: [ApiResponse] = []
var body: some View {
List(model) { response in
Text(response.post.title)
}
.onAppear {
getPosts() { results in
model = results
}
}
}
func getPosts(completion: @escaping ([ApiResponse]) -> Void) {
let mainURL = "https://fastapi-daniel855.herokuapp.com/"
let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjozLCJleHAiOjE2NzUwOTI2Nzl9.V-nvE7oybzXIetq8dr2qlXrxBtrnBeJQ36D0yEZUDu0"
let headers: HTTPHeaders = [
"Authorization": "Bearer \(token)",
"Content-type": "application/json"
]
AF.request("\(mainURL)posts/", method: .get, headers: headers).responseDecodable(of: [ApiResponse].self) { response in
debugPrint(response)
switch response.result {
case .success(let results): completion(results)
case .failure(_): completion([]) // <-- errors, todo
}
}
}
}