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)
}
}
}