How can I receive a http request in Java/Python? - swift

I am quite new to HTTP requests, I am currently building an app which sends a question to a server, the server sends a response which the app receives and displays on the screen. This is the Swift code I use:
let url = URL(string: "https://reqres.in/api/users?page=2")!
var request = URLRequest(url: url)
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpMethod = "POST"
request.httpBody = encoded
print("started request")
URLSession.shared.dataTask(with: request) { data, response, error in
// handle the result here
}.resume()
I have already done a lot of research, but I just found code for sending an HTTP request from Java/Python, not receiving one. I am running my own PC at home which should work as a server, what code do I need in Python/Java to receive the request from Swift and respond to it?

I think that quickest way would be running spring boot app with #RestController class and #PostMapping method inside that will handle your request.
You'll need to create spring boot project with Spring Web dependency from https://start.spring.io/
Download it and add new file with controller class that will handle your rest requests.
Example controller:
#RestController
public class ExamplaryController {
#PostMapping(value = "api/users")
public ResponseEntity<WhateverTypeYouWantToBeReturned> putDataExample(#RequestParam Integer page) {
//code smth here
return result;
}
}

Related

Internal Server Error - 500. Object reference not set to an instance of an object. step 0

I am making a POST API call from my swiftUI code. I have made sure my API call code is working in SwiftUI and I tested that with other urls. The issue is the same API call works from my NativeScript Angular code but it doesn't work from my swiftUI code and throws this following error.
Internal Server Error - 500. Object reference not set to an instance of an object. step 0
This is how I am making a request in NativeScript Angular which works fine.
let url = "some_url/signIn?email=${userName}&password=${password}"
const httpOptions = {
headers: new HttpHeaders({ "Content-Type": "application/json" }),
};
this._http.post<User>(url, httpOptions).subscribe((results: any) => { /* data processing */ } )
Where this._http is injected in the constructor.
Following is how I am making the API call in swift which throws an error.
guard let url = URL(string: "some_url/signIn?email=\(userName)&password=\(password)") else {fatalError("Missing URL")}
var urlRequest = URLRequest(url: url)
urlRequest.httpMethod = "POST"
let (data, response) = try await URLSession.shared.data(for: urlRequest)
guard(response as? HTTPURLResponse)?.statusCode == 200 else {fatalError("Error while fetching data")}
This last line is where the error occurs.
I have never seen this error before and can't find any good results.
Any kind of information would be helpful.
Thank you in advance :)
I figured out the issue,
I just became aware that I was passing headers in my NativeScript Angular code, but not in my SwiftUI code.
I just simply added this line and the API call on SwiftUI works fine now.
urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")

Why response is always {"detail":"Unsupported media type \"text/plain\" in request."} in swift?

I have created a sample app in Django which deletes a question from App. And provides a correct output when consumed using POSTMAN.
class Questions(APIView):
def delete(self,request):
received_id = request.POST["id"]
print(received_id)
place = Question.objects.get(pk=received_id)
place.delete()
questions = Question.objects.all()
seriliazer = QuestionSerializer(questions,many = True)
return Response({'Orgs': seriliazer.data})
However, when I am trying to achieve it from iOS app, it's returning {"detail":"Unsupported media type "text/plain" in request."}
func deleteQuestion( id: Int){
guard let url = URL(string: "http://127.0.0.1:8000/V1/API/questions/") else {
return
}
var request = URLRequest(url: url)
let postString = "id=15"
request.httpBody = postString.data(using: String.Encoding.utf8);
request.httpMethod = "DELETE"
URLSession.shared.dataTask(with: request) { data, response, error in
let str = String(decoding: data!, as: UTF8.self)
print(str)
if error == nil {
self.fetcOrganizatinData()
}
}.resume()
}
Could not really understand where exactly the problem is ?
If the api is expecting Json, the body you are sending is not Json, it’s encoded plain text. If it should be Json you can change the body string into the Json format like:
“{\”id\”:15}”
// you may want to tell it what you’re sending
request.setValue("application/json", forHTTPHeaderField: "Accept-Encoding")
Another thing it could be is the request is missing the Accept-Encoding header which tells the api what you’re sending up where Content-Type is what the api typically sends down.
I’ve experienced header injection when I’ve sent requests through specific gateways that aren’t always right. I’d the header isn’t present, something along the way could try to help you out and add the header. This has caused me problems on the past. I still don’t know exactly where in our stack it was occurring, but adding the header fixed my problem.
You can add the header like:
request.setValue("charset=utf-8", forHTTPHeaderField: "Accept-Encoding")
DELETE request's body will be ignored, I could guess from the Is an entity body allowed for an HTTP DELETE request? post. HENCE Better to send the complete URL or in header itself,
so I made the function as below
def delete(self,request):
received_id = request.headers['id']
place = Question.objects.get(pk=received_id)
place.delete()
return HttpResponse("DELETE view is working fine ")
and swift
func deleteQuestion( id: Int){
guard let url = URL(string: "http://127.0.0.1:8000/V1/API/questions/") else {
return
}
var request = URLRequest(url: url)
//let postString = "id=\(id)"
// request.httpBody = postString.data(using: String.Encoding.utf8);
request.httpMethod = "DELETE"
request.setValue("charset=utf-8", forHTTPHeaderField: "Accept-Encoding")
request.setValue("charset=utf-8", forHTTPHeaderField: "Content-Type")
request.setValue("\(id)", forHTTPHeaderField: "id")
URLSession.shared.dataTask(with: request) { data, response, error in
let str = String(decoding: data!, as: UTF8.self)
print(str)
if error == nil {
self.fetcOrganizatinData()
}
}.resume()
}
Shortly add Content-Type application/json in your headers
Reason
this happens because the postman has some default headers usually 8.
One of them is
Content-Type text/plain
and by writing "Content-Type": "application/json" we can overwrite that rule.
So whenever you want to pass your data like JSON do that.
to learn more what is by default in postman
I recommend you to read this official documentation of postman.
It happens with me I solved this with overwriting default Content-Type

How to call a post web service with UrlSession.DataTaskPublisher?

I have a simple question that I can see only dataTaskPublisher in documentation with which I was able to call a get web service but how can I call a post web service which can return a publisher?
you can define a request and call it in your dataTaskPublisher like this :
var request = URLRequest(url: URL(string: "url")!)
let session = URLSession.shared
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
request.HTTPBody = try! JSONSerialization.dataWithJSONObject(parameters, options: [])
session.dataTaskPublisher(for: request)
Use constructor with URLRequest and prepare request with any HTTP method you need.
/// Returns a publisher that wraps a URL session data task for a given URL request.
///
/// The publisher publishes data when the task completes, or terminates if the task fails with an error.
/// - Parameter request: The URL request for which to create a data task.
/// - Returns: A publisher that wraps a data task for the URL request.
public func dataTaskPublisher(for request: URLRequest) -> URLSession.DataTaskPublisher

Attempts to access rapidAPI yahoo finance give me error 403 through swift

I am trying to use rapidAPI to access the Yahoo Finance API for a personal project. I registered for a free account and got an API key. Rapid API allows their users to copy and paste code to request data, so I took their demo code for accessing the API. Here it is for swift when trying to access details about a stock:
import Foundation
let headers = [
"x-rapidapi-host": "apidojo-yahoo-finance-v1.p.rapidapi.com",
"x-rapidapi-key": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" //private key
]
let request = NSMutableURLRequest(url: NSURL(string: "https://apidojo-yahoo-finance-
v1.p.rapidapi.com/stock/get-detail?region=US&lang=en&symbol=APPL")! as URL,
cachePolicy: .useProtocolCachePolicy,
timeoutInterval: 10.0)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers
let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
if (error != nil) {
print(error)
} else {
let httpResponse = response as? HTTPURLResponse
print(httpResponse)
}
})
dataTask.resume()
When I run this code, it gives me error 403. This means that this data is forbidden according to their website. I have tried using other APIs and copying and pasting the demo code and they work fine. This API shouldn't be depreciated because it is running on the website demo. Here is the returning message I was given in Xcode:
I just checked Yahoo Finance API. The GET /get-detail endpoint seems to be deprecated now. Despite the fact that it's deprecated, it's still working for me.
Make sure to subscribe to this API. this could be the cause of the 403 code

Send Firebase Swift Push using NSURLSession HTTP Post

I set up my app so that users when they login subscribe to a topic with their user UID. Whenever a user sends a message to another user I will be calling the function below that I am hoping to trigger the push.
func sendPushNotification(toUser: String, message: String) {
let urlString = "https://fcm.googleapis.com/fcm/send"
let topic = "\topic\\(toUser)"
let url = NSURL(string: urlString)!
let paramString = "to=\(topic)"
let request = NSMutableURLRequest(URL: url)
request.HTTPMethod = "POST"
request.HTTPBody = paramString.dataUsingEncoding(NSUTF8StringEncoding)!
request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { (data, response, error) in
do {
if let jsonData = data {
if let jsonDataDict = try NSJSONSerialization.JSONObjectWithData(jsonData, options: NSJSONReadingOptions.AllowFragments) as? [String: AnyObject] {
NSLog("Received data:\n\(jsonDataDict))")
}
}
} catch let err as NSError {
print(err.debugDescription)
}
}
task.resume()
}
Based on Firebase docs I am supposed to do this HTTP request:
Send to a single topic:
https://fcm.googleapis.com/fcm/send
Content-Type:application/json
Authorization:key=AIzaSyZ-1u...0GBYzPu7Udno5aA
{
"to": "/topics/foo-bar",
"data": {
"message": "This is a Firebase Cloud Messaging Topic Message!",
}
}
I am struggling to see what I pass in the paramString for the message to be sent based off of their example. Also, where do I define the Authorization:key=
Sending a message with Firebase Cloud Messaging requires that you provide your server key in the Authorization header. As the name suggests, this key should only be used in code that runs on an app server (or other infrastructure that you control). Putting the server key into the app that you ship to your users, means malicious users can use it to send messages on your behalf.
From the Firebase documentation on sending messages to topics (emphasis mine):
From the server side, sending messages to a Firebase Cloud Messaging topic is very similar to sending messages to an individual device or to a user group. The app server sets the to key with a value like /topics/yourTopic.