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.conn.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.conn.Send, }, httpRequest) mount.conn.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), }) }