0

I'm sending my package with the following code:

func post() {
    let server = "serverURLHere"
    guard let url  = URL(string: server) else { return }
    // background task to make request with URLSession
    var urlRequest = URLRequest(url: url)
    urlRequest.httpMethod = "POST"
    guard let data = try? JSONEncoder().encode("testPackage") else { return }
    // I also tried defining a variable as a string and then using .data(using: String.Encoding.utf8) on it but that didn't help at all.
    urlRequest.httpBody = data
    let task = URLSession.shared.dataTask(with: urlRequest) {
        (data, response, error) in
        if let error = error {
            print(error)
            return
        }
        guard let data = data else {return}
        guard let dataString = String(data: data, encoding: String.Encoding.utf8) else {return}
        // update the UI if all went OK
        DispatchQueue.main.async {
            print("the data we got back was \(dataString)")
        }
    }
    // start the task
    task.resume()
}

On the server side, it looks like:

const express = require('express');
const app = express();
const http = require('http').Server(app);
const port = process.env.PORT || 5000;
const util = require('util')

app.use(express.json());
app.use(express.urlencoded({ extended: true }))
app.use(express.static(__dirname + '/public'));

http.on('request', (request, response) => {
  console.log("the method request was " + request.method)
  if (request.method == "GET") {
    console.log("GET")
  } else if (request.method == "POST") {
    console.log("POST")
    console.log("request: " + request)
    console.log("request.body: " + request.body)
  }

  request.on('error', (err) => {
    // This prints the error message and stack trace to `stderr`.
    console.error("the error was " + err);
  });
  // console.log("got a request from the swifty server")
});

http.listen(port, () => console.log('listening on port ' + port));

request and request.body are both objects, but I thought request.body would contain a JSON object with the data I encoded on the client side...yet when I try to parse it, there's a big error that causes the server to crash (I think because it's empty). Not sure what to do...thanks for any help in advance!

This is the error that appears when I uncomment the console.log(JSON.parse(request.body)) line of code:

https://i.stack.imgur.com/pOIHq.jpg

When I run console.log the util.inspect on the request.body, I get the '{}':

https://i.stack.imgur.com/9KoCW.png

nickcoding2
  • 142
  • 1
  • 8
  • 34
  • "*there's a big error that causes the server to crash*" - what is the error message? – Bergi Apr 11 '21 at 17:37
  • "*I thought request.body would contain a JSON object*" - it does, doesn't it? You said yourself that `request.body` is an object already. Does it contain the expected data? If not, what *does* it contain? "*when I try to parse it*" - notice that the `express.json()` middleware your app is using does the parsing already. You cannot `JSON.parse` it again. – Bergi Apr 11 '21 at 17:38
  • @Bergi I updated my code with images of the output of printing the request.body object and the error that appears when I tried to parse it (although you said this is unnecessary). If I try printing out the request object, I get a HUGE amount of information that I could also post, let me know if that would help! – nickcoding2 Apr 11 '21 at 18:08
  • Yes, [that's the expected classical error message for trying to parse an object instead of a string](https://stackoverflow.com/q/8081701/1048572). – Bergi Apr 11 '21 at 18:34
  • It seems that your Swift code does indeed send an empty object as the payload. Try to verify what you're sending by debugging your client code or printing `urlRequest.httpBody`. – Bergi Apr 11 '21 at 18:35
  • @Bergi When I print urlRequest.httpBody is just says that it's '13 bytes' – nickcoding2 Apr 11 '21 at 18:36
  • I don't know Swift but it seems that is the problem. What is the expected HTTP body this script should send? – Bergi Apr 11 '21 at 18:38
  • @Bergi Honestly, I'm not sure exactly what the httpBody should look like because all I know is that I'm encoding it using the JSON encoder so I would think it would format itself in JSON, but I really have no idea why it isn't actually sending anything in the data packet to the server... – nickcoding2 Apr 11 '21 at 18:51
  • I guess you should figure this out first then :-) Defining the API contract between the two programs should be the first step. `{}` is valid JSON, so formatting something as JSON seems to work, but still it's not what you expect the JSON to contain. – Bergi Apr 11 '21 at 18:53
  • Well, I essentially just want to send a string that I made in Swift over to my server. I thought encoding it in JSON would be the best way to do it, but now I'm realizing...is JSON just dictionaries? Are the strings implicitly turned into a dictionary that represents that string (because that's what I thought happens)? – nickcoding2 Apr 11 '21 at 18:57
  • JSON is a representation for nested data structures, including strings, but it seems your encoding function treated the string as an (empty) object? If you really want to send only a string, there's no reason to use JSON - just send the raw string as the HTTP body. Give it an appropriate `Content-Type` if you want to do it cleanly. – Bergi Apr 11 '21 at 19:02
  • @Bergi When I try setting urlRequest.httpBody to a string, it says that it must be of type "Data" which is why you either need to JSONEncoder().encode it or do String.data(using: String.Encodable.utf8), but neither of those are working... – nickcoding2 Apr 11 '21 at 20:28

0 Answers0