summaryrefslogtreecommitdiffhomepage
path: root/go/request.go
diff options
context:
space:
mode:
Diffstat (limited to 'go/request.go')
-rw-r--r--go/request.go144
1 files changed, 144 insertions, 0 deletions
diff --git a/go/request.go b/go/request.go
new file mode 100644
index 00000000..1d8c6702
--- /dev/null
+++ b/go/request.go
@@ -0,0 +1,144 @@
+/*
+ * 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)
+}