Reading json post requests sent by http

I have been struggling for hours trying to get access to the json that has been sent via http by a client application. Once I can get at it I can get my code to deal with it and respond, I just can get past the server side of this.

I can read all the information about the POST, type, size, length, source, but not the POST itself, and the server works just fine for displaying simple pages. I've included my terminal response and my code, id be really grateful if someone could help me access the hidden bytes.

OST /api/v1 HTTP/1.1
Host: localhost:7860
Content-Type: application/json
Connection: keep-alive
Accept: */*
User-Agent: TheApp/10 CFNetwork/1492.0.1 Darwin/23.3.0
Content-Length: 47
Accept-Language: en-GB,en;q=0.9
Accept-Encoding: gzip, deflate
import SwiftUI

class PicoHttpServer {
    private static var serverSocket: Int32?
    private static let queue = DispatchQueue(label: "com.pico.http.server.queue")
    private static let semaphore = DispatchSemaphore(value: 1)
    static func httpOkResponse(html: String) -> String {
        return "HTTP/1.1 200 OK\r\nServer: PicoHttpServer\r\nContent-Length: \(html.count)\r\n\r\n\(html)"
    }
    static func start(port: UInt16 = hostPort, address: UInt32 = INADDR_LOOPBACK, requestHandler: @escaping ((String) -> String)) {
        semaphore.wait()
        let started = serverSocket != nil
        semaphore.signal()
        if started {
            return
        }
        queue.async {
            realStart(port: port, address: address, requestHandler: requestHandler)
        }
    }
    static func stop() {
        semaphore.wait()
        if let serverSocker = serverSocket {
            close(serverSocker)
        }
        serverSocket = nil
        semaphore.signal()
    }
    private static func realStart(port: UInt16, address: UInt32, requestHandler: ((String) -> String)) {
        let tcpSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)
        if tcpSocket == -1 {
            return
        }
        serverSocket = tcpSocket
        var reuseOn = Int32(1)
        setsockopt(tcpSocket, SOL_SOCKET, SO_REUSEADDR, &reuseOn, socklen_t(MemoryLayout.size(ofValue: reuseOn)))
        var socketAddress = sockaddr_in()
        socketAddress.sin_family = sa_family_t(AF_INET)
        socketAddress.sin_port = port.bigEndian
        socketAddress.sin_addr = in_addr(s_addr: address.bigEndian)
        socketAddress.sin_zero = (0, 0, 0, 0, 0, 0, 0, 0)
        let socklen = UInt8(socklen_t(MemoryLayout<sockaddr_in>.size))
        let bindResult = withUnsafePointer(to: &socketAddress) { sockaddrInPtr -> Int32 in
            let sockaddrPtr = UnsafeRawPointer(sockaddrInPtr).assumingMemoryBound(to: sockaddr.self)
            return bind(tcpSocket, sockaddrPtr, socklen_t(socklen))
        }
        if bindResult == -1 {
            return
        }
        let listenResult = listen(tcpSocket, 5)
        if listenResult == -1 {
            return
        }
        print("Server started")
        while(true) {
            semaphore.wait()
            let stopped = serverSocket == nil
            semaphore.signal()
            if stopped {
                break
            }
            let mtu = 65536
            let client = accept(tcpSocket, nil, nil)
            if client == -1 {
                continue
            }
            var buffer = Data(repeating: 0, count: mtu)
            let readResult = buffer.withUnsafeMutableBytes { pointer in
                return read(client, pointer.baseAddress, mtu)
            }
            if readResult == -1 {
                continue
            }
            let clientData = buffer.subdata(in: 0..<readResult)
//            print("client data = \(clientData)")
            let urlContent = NSString(data: buffer, encoding: String.Encoding.ascii.rawValue)
//            print(" buffer = \(urlContent!)")
            
            
//            print(" buffer = \(urlContent!)")
//            print("client buffer = \(buffer)")
//            print("just data?? = \(String(describing: start))")
            let clientRequest = String(data: clientData, encoding: .utf8) ?? ""
//            print("client read = \(readResult)")
            let response = requestHandler(clientRequest)
//            print("read  = \(String(describing: read))")
            response.withCString { bytes in
              write(client, bytes, Int(strlen(bytes)))
              close(client)
            }
        }
        print("Server stopped")
    }
}



struct serverView: View {
    
    var body: some View {
        
        Text("DrawOmatic server test, please visit localhost:7860 to check if working.")
            .padding()
        HStack {
            Text("Port")
//            TextField("port", value: hostPort, format: .number)
//                .textFieldStyle(.roundedBorder)
//                .padding()
            
            TextField("\(hostPort)", text: Binding(
                        get: { (hostPort != nil) ? String(hostPort) : "" },
                        set: { hostPort = UInt16($0.filter { "0123456789".contains($0) }) ?? 7860 })
                    )
            
            
        }
        Button {
            Task {
                
                PicoHttpServer.start { request in
                    if request.hasPrefix("GET /1.html") {
                        return PicoHttpServer.httpOkResponse(html: "<html><body>Page 1</body></html>")
                    } else if request.hasPrefix("GET /2.html") {
                        return PicoHttpServer.httpOkResponse(html: "<html><body>Page 2</body></html>")
                    } else {
                        print("Welcome to the site,\(request)")
                        return PicoHttpServer.httpOkResponse(html: "<html><body>Welcome To the site</body></html>")
                    }
                }
                
            }
        } label: {
            Text("server start", comment: "server start")
                .frame(minWidth:30)
            
        }
        Button {
            Task {
                
                PicoHttpServer.stop()
                
            }
        } label: {
            Text("server stop", comment: "server start")
                .frame(minWidth:30)
            
        }
        
        
        
    }
}

I've not rigged in details, but I would look at:

Content-Length: 47

The Content-Length header is a number denoting an the exact byte length of the HTTP body. The HTTP body starts immediately after the first empty line that is found after the start-line and headers.

Is 47 the value you expect ?

47 is just fine, it is a short piece of json. The app sending the json works with other software, and other json apps work with my software. I can't find out what is allowing one and not the other.

Reading json post requests sent by http
 
 
Q