145 lines
3.0 KiB
Go
145 lines
3.0 KiB
Go
/*
|
|
* Copyright (C) Max Romanov
|
|
* Copyright (C) NGINX, Inc.
|
|
*/
|
|
|
|
package unit
|
|
|
|
/*
|
|
#include "nxt_cgo_lib.h"
|
|
*/
|
|
import "C"
|
|
|
|
import (
|
|
"io"
|
|
"net/http"
|
|
"net/url"
|
|
"crypto/tls"
|
|
"unsafe"
|
|
)
|
|
|
|
type request struct {
|
|
req http.Request
|
|
resp *response
|
|
c_req C.uintptr_t
|
|
}
|
|
|
|
func (r *request) Read(p []byte) (n int, err error) {
|
|
res := C.nxt_cgo_request_read(r.c_req, buf_ref(p), C.uint32_t(len(p)))
|
|
|
|
if res == 0 && len(p) > 0 {
|
|
return 0, io.EOF
|
|
}
|
|
|
|
return int(res), nil
|
|
}
|
|
|
|
func (r *request) Close() error {
|
|
C.nxt_cgo_request_close(r.c_req)
|
|
return nil
|
|
}
|
|
|
|
func (r *request) response() *response {
|
|
if r.resp == nil {
|
|
r.resp = new_response(r.c_req, &r.req)
|
|
}
|
|
|
|
return r.resp
|
|
}
|
|
|
|
func (r *request) done() {
|
|
resp := r.response()
|
|
if !resp.headerSent {
|
|
resp.WriteHeader(http.StatusOK)
|
|
}
|
|
C.nxt_cgo_request_done(r.c_req, 0)
|
|
}
|
|
|
|
func get_request(go_req uintptr) *request {
|
|
return (*request)(unsafe.Pointer(go_req))
|
|
}
|
|
|
|
//export nxt_go_request_create
|
|
func nxt_go_request_create(c_req C.uintptr_t,
|
|
c_method *C.nxt_cgo_str_t, c_uri *C.nxt_cgo_str_t) uintptr {
|
|
|
|
uri := C.GoStringN(c_uri.start, c_uri.length)
|
|
|
|
var URL *url.URL
|
|
var err error
|
|
if URL, err = url.ParseRequestURI(uri); err != nil {
|
|
return 0
|
|
}
|
|
|
|
r := &request{
|
|
req: http.Request{
|
|
Method: C.GoStringN(c_method.start, c_method.length),
|
|
URL: URL,
|
|
Header: http.Header{},
|
|
Body: nil,
|
|
RequestURI: uri,
|
|
},
|
|
c_req: c_req,
|
|
}
|
|
r.req.Body = r
|
|
|
|
return uintptr(unsafe.Pointer(r))
|
|
}
|
|
|
|
//export nxt_go_request_set_proto
|
|
func nxt_go_request_set_proto(go_req uintptr, proto *C.nxt_cgo_str_t,
|
|
maj C.int, min C.int) {
|
|
|
|
r := get_request(go_req)
|
|
r.req.Proto = C.GoStringN(proto.start, proto.length)
|
|
r.req.ProtoMajor = int(maj)
|
|
r.req.ProtoMinor = int(min)
|
|
}
|
|
|
|
//export nxt_go_request_add_header
|
|
func nxt_go_request_add_header(go_req uintptr, name *C.nxt_cgo_str_t,
|
|
value *C.nxt_cgo_str_t) {
|
|
|
|
r := get_request(go_req)
|
|
r.req.Header.Add(C.GoStringN(name.start, name.length),
|
|
C.GoStringN(value.start, value.length))
|
|
}
|
|
|
|
//export nxt_go_request_set_content_length
|
|
func nxt_go_request_set_content_length(go_req uintptr, l C.int64_t) {
|
|
get_request(go_req).req.ContentLength = int64(l)
|
|
}
|
|
|
|
//export nxt_go_request_set_host
|
|
func nxt_go_request_set_host(go_req uintptr, host *C.nxt_cgo_str_t) {
|
|
get_request(go_req).req.Host = C.GoStringN(host.start, host.length)
|
|
}
|
|
|
|
//export nxt_go_request_set_url
|
|
func nxt_go_request_set_url(go_req uintptr, scheme *C.char) {
|
|
get_request(go_req).req.URL.Scheme = C.GoString(scheme)
|
|
}
|
|
|
|
//export nxt_go_request_set_remote_addr
|
|
func nxt_go_request_set_remote_addr(go_req uintptr, addr *C.nxt_cgo_str_t) {
|
|
|
|
get_request(go_req).req.RemoteAddr = C.GoStringN(addr.start, addr.length)
|
|
}
|
|
|
|
//export nxt_go_request_set_tls
|
|
func nxt_go_request_set_tls(go_req uintptr) {
|
|
|
|
get_request(go_req).req.TLS = &tls.ConnectionState{ }
|
|
}
|
|
|
|
//export nxt_go_request_handler
|
|
func nxt_go_request_handler(go_req uintptr, h uintptr) {
|
|
r := get_request(go_req)
|
|
handler := get_handler(h)
|
|
|
|
go func(r *request) {
|
|
handler.ServeHTTP(r.response(), &r.req)
|
|
r.done()
|
|
}(r)
|
|
}
|