2023-05-25 16:08:56 -06:00
|
|
|
package service
|
|
|
|
|
|
|
|
import "io"
|
|
|
|
import "log"
|
|
|
|
import "net/http"
|
|
|
|
import "hnakra/protocol"
|
|
|
|
|
|
|
|
func (mount *HTTP) handle (request protocol.MessageHTTPRequest) {
|
|
|
|
log.Println("->?", request.Address, "requests", request.URL)
|
|
|
|
bodyReader := &bodyReader {
|
|
|
|
id: request.ID,
|
|
|
|
reader: mount.requests.readerFor(request.ID),
|
2023-05-29 15:03:27 -06:00
|
|
|
send: mount.conn.Send,
|
2023-05-25 16:08:56 -06:00
|
|
|
close: func () { mount.requests.end(request.ID) },
|
|
|
|
}
|
|
|
|
defer mount.requests.remove(request.ID)
|
|
|
|
|
|
|
|
handler := mount.Handler
|
|
|
|
if handler == nil {
|
|
|
|
handler = http.DefaultServeMux
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO possibly populate the http version and ContentLength
|
|
|
|
// TODO: if there is an error, send an error status to the server
|
|
|
|
httpRequest, _ := http.NewRequest(request.Method, request.URL, bodyReader)
|
|
|
|
httpRequest.Header = http.Header(request.Header)
|
|
|
|
|
|
|
|
handler.ServeHTTP(&responseWriter {
|
|
|
|
id: request.ID,
|
|
|
|
header: make(http.Header),
|
2023-05-29 15:03:27 -06:00
|
|
|
send: mount.conn.Send,
|
2023-05-25 16:08:56 -06:00
|
|
|
}, httpRequest)
|
|
|
|
|
2023-05-29 15:03:27 -06:00
|
|
|
mount.conn.Send(protocol.MessageHTTPBodyEnd { ID: request.ID })
|
2023-05-25 16:08:56 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
type bodyReader struct {
|
|
|
|
reader io.Reader
|
|
|
|
requested bool
|
|
|
|
id protocol.ID
|
|
|
|
send func (protocol.Message) error
|
|
|
|
close func ()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (reader *bodyReader) Read (buffer []byte) (amount int, err error) {
|
|
|
|
if !reader.requested {
|
|
|
|
err = reader.send(protocol.MessageHTTPBodyRequest {
|
|
|
|
ID: reader.id,
|
|
|
|
})
|
|
|
|
if err != nil { return }
|
|
|
|
reader.requested = true
|
|
|
|
}
|
|
|
|
return reader.reader.Read(buffer)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (reader *bodyReader) Close () error {
|
|
|
|
// TODO: possibly make this mthd ask the server to stop sending body
|
|
|
|
// segments
|
|
|
|
reader.close()
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
type responseWriter struct {
|
|
|
|
header http.Header
|
|
|
|
wroteHeader bool
|
|
|
|
id protocol.ID
|
|
|
|
send func (protocol.Message) error
|
|
|
|
}
|
|
|
|
|
|
|
|
func (writer *responseWriter) Header () http.Header {
|
|
|
|
return writer.header
|
|
|
|
}
|
|
|
|
|
|
|
|
func (writer *responseWriter) Write (buffer []byte) (amount int, err error) {
|
|
|
|
if !writer.wroteHeader {
|
|
|
|
writer.WriteHeader(http.StatusOK)
|
|
|
|
}
|
|
|
|
|
|
|
|
for len(buffer) > 0 {
|
|
|
|
sent := int(protocol.MaxIntOfSize(2) - 1)
|
|
|
|
if len(buffer) < sent {
|
|
|
|
sent = len(buffer)
|
|
|
|
}
|
|
|
|
err = writer.send(protocol.MessageHTTPBodySegment {
|
|
|
|
ID: writer.id,
|
|
|
|
Data: buffer[:sent],
|
|
|
|
})
|
|
|
|
if err != nil { return }
|
|
|
|
buffer = buffer[sent:]
|
|
|
|
amount += sent
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (writer *responseWriter) WriteHeader (statusCode int) {
|
|
|
|
if writer.wroteHeader { return }
|
|
|
|
|
|
|
|
writer.wroteHeader = true
|
|
|
|
writer.send(protocol.MessageHTTPResponse {
|
|
|
|
ID: writer.id,
|
|
|
|
Status: uint16(statusCode),
|
|
|
|
Header: protocol.Map(writer.header),
|
|
|
|
})
|
|
|
|
}
|