1/* 2 * Copyright (C) Max Romanov 3 * Copyright (C) NGINX, Inc. 4 */ 5 6package unit 7 8/* 9#include "nxt_cgo_lib.h" 10*/ 11import "C" 12 13import ( 14 "io" 15 "net/http" 16 "net/url" 17 "crypto/tls" 18 "unsafe" 19) 20 21type request struct { 22 req http.Request 23 resp *response 24 c_req C.uintptr_t 25} 26 27func (r *request) Read(p []byte) (n int, err error) { 28 res := C.nxt_cgo_request_read(r.c_req, buf_ref(p), C.uint32_t(len(p))) 29 30 if res == 0 && len(p) > 0 { 31 return 0, io.EOF 32 } 33 34 return int(res), nil 35} 36 37func (r *request) Close() error { 38 C.nxt_cgo_request_close(r.c_req) 39 return nil 40} 41 42func (r *request) response() *response { 43 if r.resp == nil { 44 r.resp = new_response(r.c_req, &r.req) 45 } 46 47 return r.resp 48} 49 50func (r *request) done() { 51 resp := r.response() 52 if !resp.headerSent { 53 resp.WriteHeader(http.StatusOK) 54 } 55 C.nxt_cgo_request_done(r.c_req, 0) 56} 57 58func get_request(go_req uintptr) *request { 59 return (*request)(unsafe.Pointer(go_req)) 60} 61 62//export nxt_go_request_create 63func nxt_go_request_create(c_req C.uintptr_t, 64 c_method *C.nxt_cgo_str_t, c_uri *C.nxt_cgo_str_t) uintptr { 65 66 uri := C.GoStringN(c_uri.start, c_uri.length) 67 68 var URL *url.URL 69 var err error 70 if URL, err = url.ParseRequestURI(uri); err != nil { 71 return 0 72 } 73 74 r := &request{ 75 req: http.Request{ 76 Method: C.GoStringN(c_method.start, c_method.length), 77 URL: URL, 78 Header: http.Header{}, 79 Body: nil, 80 RequestURI: uri, 81 }, 82 c_req: c_req, 83 } 84 r.req.Body = r 85 86 return uintptr(unsafe.Pointer(r)) 87} 88 89//export nxt_go_request_set_proto 90func nxt_go_request_set_proto(go_req uintptr, proto *C.nxt_cgo_str_t, 91 maj C.int, min C.int) { 92 93 r := get_request(go_req) 94 r.req.Proto = C.GoStringN(proto.start, proto.length) 95 r.req.ProtoMajor = int(maj) 96 r.req.ProtoMinor = int(min) 97} 98 99//export nxt_go_request_add_header 100func nxt_go_request_add_header(go_req uintptr, name *C.nxt_cgo_str_t, 101 value *C.nxt_cgo_str_t) { 102 103 r := get_request(go_req) 104 r.req.Header.Add(C.GoStringN(name.start, name.length), 105 C.GoStringN(value.start, value.length)) 106} 107 108//export nxt_go_request_set_content_length 109func nxt_go_request_set_content_length(go_req uintptr, l C.int64_t) { 110 get_request(go_req).req.ContentLength = int64(l) 111} 112 113//export nxt_go_request_set_host 114func nxt_go_request_set_host(go_req uintptr, host *C.nxt_cgo_str_t) { 115 get_request(go_req).req.Host = C.GoStringN(host.start, host.length) 116} 117 118//export nxt_go_request_set_url 119func nxt_go_request_set_url(go_req uintptr, scheme *C.char) { 120 get_request(go_req).req.URL.Scheme = C.GoString(scheme) 121} 122 123//export nxt_go_request_set_remote_addr 124func nxt_go_request_set_remote_addr(go_req uintptr, addr *C.nxt_cgo_str_t) { 125 126 get_request(go_req).req.RemoteAddr = C.GoStringN(addr.start, addr.length) 127} 128 129//export nxt_go_request_set_tls 130func nxt_go_request_set_tls(go_req uintptr) { 131 132 get_request(go_req).req.TLS = &tls.ConnectionState{ } 133} 134 135//export nxt_go_request_handler 136func nxt_go_request_handler(go_req uintptr, h uintptr) { 137 r := get_request(go_req) 138 handler := get_handler(h) 139 140 go func(r *request) { 141 handler.ServeHTTP(r.response(), &r.req) 142 r.done() 143 }(r) 144} 145