hnakra/service/handle.go

105 lines
2.4 KiB
Go

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),
send: mount.send,
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),
send: mount.send,
}, httpRequest)
mount.send(protocol.MessageHTTPBodyEnd { ID: request.ID })
}
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),
})
}