11316Smax.romanov@nginx.com/* 21316Smax.romanov@nginx.com * Copyright (C) Max Romanov 31316Smax.romanov@nginx.com * Copyright (C) NGINX, Inc. 41316Smax.romanov@nginx.com */ 51316Smax.romanov@nginx.com 61316Smax.romanov@nginx.compackage unit 71316Smax.romanov@nginx.com 81316Smax.romanov@nginx.com/* 91316Smax.romanov@nginx.com#include "nxt_cgo_lib.h" 101316Smax.romanov@nginx.com*/ 111316Smax.romanov@nginx.comimport "C" 121316Smax.romanov@nginx.com 131316Smax.romanov@nginx.comimport ( 141316Smax.romanov@nginx.com "io" 151316Smax.romanov@nginx.com "net/http" 161316Smax.romanov@nginx.com "net/url" 171316Smax.romanov@nginx.com "crypto/tls" 181316Smax.romanov@nginx.com "unsafe" 191316Smax.romanov@nginx.com) 201316Smax.romanov@nginx.com 211316Smax.romanov@nginx.comtype request struct { 22*1713Smax.romanov@nginx.com req http.Request 23*1713Smax.romanov@nginx.com resp response 24*1713Smax.romanov@nginx.com c_req *C.nxt_unit_request_info_t 251316Smax.romanov@nginx.com} 261316Smax.romanov@nginx.com 271316Smax.romanov@nginx.comfunc (r *request) Read(p []byte) (n int, err error) { 281316Smax.romanov@nginx.com res := C.nxt_cgo_request_read(r.c_req, buf_ref(p), C.uint32_t(len(p))) 291316Smax.romanov@nginx.com 301316Smax.romanov@nginx.com if res == 0 && len(p) > 0 { 311316Smax.romanov@nginx.com return 0, io.EOF 321316Smax.romanov@nginx.com } 331316Smax.romanov@nginx.com 341316Smax.romanov@nginx.com return int(res), nil 351316Smax.romanov@nginx.com} 361316Smax.romanov@nginx.com 371316Smax.romanov@nginx.comfunc (r *request) Close() error { 381316Smax.romanov@nginx.com return nil 391316Smax.romanov@nginx.com} 401316Smax.romanov@nginx.com 41*1713Smax.romanov@nginx.comfunc new_request(c_req *C.nxt_unit_request_info_t) (r *request, err error) { 42*1713Smax.romanov@nginx.com req := c_req.request 43*1713Smax.romanov@nginx.com 44*1713Smax.romanov@nginx.com uri := GoStringN(&req.target, C.int(req.target_length)) 45*1713Smax.romanov@nginx.com 46*1713Smax.romanov@nginx.com URL, err := url.ParseRequestURI(uri) 47*1713Smax.romanov@nginx.com if err != nil { 48*1713Smax.romanov@nginx.com return nil, err 491316Smax.romanov@nginx.com } 501316Smax.romanov@nginx.com 51*1713Smax.romanov@nginx.com proto := GoStringN(&req.version, C.int(req.version_length)) 521316Smax.romanov@nginx.com 53*1713Smax.romanov@nginx.com r = &request{ 54*1713Smax.romanov@nginx.com req: http.Request { 55*1713Smax.romanov@nginx.com URL: URL, 56*1713Smax.romanov@nginx.com Header: http.Header{}, 57*1713Smax.romanov@nginx.com RequestURI: uri, 58*1713Smax.romanov@nginx.com Method: GoStringN(&req.method, C.int(req.method_length)), 59*1713Smax.romanov@nginx.com Proto: proto, 60*1713Smax.romanov@nginx.com ProtoMajor: 1, 61*1713Smax.romanov@nginx.com ProtoMinor: int(proto[7] - '0'), 62*1713Smax.romanov@nginx.com ContentLength: int64(req.content_length), 63*1713Smax.romanov@nginx.com Host: GoStringN(&req.server_name, C.int(req.server_name_length)), 64*1713Smax.romanov@nginx.com RemoteAddr: GoStringN(&req.remote, C.int(req.remote_length)), 65*1713Smax.romanov@nginx.com }, 66*1713Smax.romanov@nginx.com resp: response{header: http.Header{}, c_req: c_req}, 67*1713Smax.romanov@nginx.com c_req: c_req, 681316Smax.romanov@nginx.com } 691316Smax.romanov@nginx.com 701316Smax.romanov@nginx.com r.req.Body = r 711316Smax.romanov@nginx.com 72*1713Smax.romanov@nginx.com if req.tls != 0 { 73*1713Smax.romanov@nginx.com r.req.TLS = &tls.ConnectionState{ } 74*1713Smax.romanov@nginx.com r.req.URL.Scheme = "https" 751316Smax.romanov@nginx.com 76*1713Smax.romanov@nginx.com } else { 77*1713Smax.romanov@nginx.com r.req.URL.Scheme = "http" 78*1713Smax.romanov@nginx.com } 79*1713Smax.romanov@nginx.com 80*1713Smax.romanov@nginx.com fields := get_fields(req) 811316Smax.romanov@nginx.com 82*1713Smax.romanov@nginx.com for i := 0; i < len(fields); i++ { 83*1713Smax.romanov@nginx.com f := &fields[i] 841316Smax.romanov@nginx.com 85*1713Smax.romanov@nginx.com n := GoStringN(&f.name, C.int(f.name_length)) 86*1713Smax.romanov@nginx.com v := GoStringN(&f.value, C.int(f.value_length)) 871316Smax.romanov@nginx.com 88*1713Smax.romanov@nginx.com r.req.Header.Add(n, v) 89*1713Smax.romanov@nginx.com } 90*1713Smax.romanov@nginx.com 91*1713Smax.romanov@nginx.com return r, nil 921316Smax.romanov@nginx.com} 931316Smax.romanov@nginx.com 94*1713Smax.romanov@nginx.comfunc get_fields(req *C.nxt_unit_request_t) []C.nxt_unit_field_t { 95*1713Smax.romanov@nginx.com f := uintptr(unsafe.Pointer(req)) + uintptr(C.NXT_FIELDS_OFFSET) 961316Smax.romanov@nginx.com 97*1713Smax.romanov@nginx.com h := &slice_header{ 98*1713Smax.romanov@nginx.com Data: unsafe.Pointer(f), 99*1713Smax.romanov@nginx.com Len: int(req.fields_count), 100*1713Smax.romanov@nginx.com Cap: int(req.fields_count), 101*1713Smax.romanov@nginx.com } 1021316Smax.romanov@nginx.com 103*1713Smax.romanov@nginx.com return *(*[]C.nxt_unit_field_t)(unsafe.Pointer(h)) 1041316Smax.romanov@nginx.com} 1051316Smax.romanov@nginx.com 1061316Smax.romanov@nginx.com//export nxt_go_request_handler 107*1713Smax.romanov@nginx.comfunc nxt_go_request_handler(c_req *C.nxt_unit_request_info_t) { 108*1713Smax.romanov@nginx.com 109*1713Smax.romanov@nginx.com go func(c_req *C.nxt_unit_request_info_t, handler http.Handler) { 110*1713Smax.romanov@nginx.com 111*1713Smax.romanov@nginx.com ctx := c_req.ctx 112*1713Smax.romanov@nginx.com 113*1713Smax.romanov@nginx.com for { 114*1713Smax.romanov@nginx.com r, err := new_request(c_req) 115*1713Smax.romanov@nginx.com 116*1713Smax.romanov@nginx.com if err == nil { 117*1713Smax.romanov@nginx.com handler.ServeHTTP(&r.resp, &r.req) 1181316Smax.romanov@nginx.com 119*1713Smax.romanov@nginx.com if !r.resp.header_sent { 120*1713Smax.romanov@nginx.com r.resp.WriteHeader(http.StatusOK) 121*1713Smax.romanov@nginx.com } 122*1713Smax.romanov@nginx.com 123*1713Smax.romanov@nginx.com C.nxt_unit_request_done(c_req, C.NXT_UNIT_OK) 124*1713Smax.romanov@nginx.com 125*1713Smax.romanov@nginx.com } else { 126*1713Smax.romanov@nginx.com C.nxt_unit_request_done(c_req, C.NXT_UNIT_ERROR) 127*1713Smax.romanov@nginx.com } 128*1713Smax.romanov@nginx.com 129*1713Smax.romanov@nginx.com c_req = C.nxt_unit_dequeue_request(ctx) 130*1713Smax.romanov@nginx.com if c_req == nil { 131*1713Smax.romanov@nginx.com break 132*1713Smax.romanov@nginx.com } 133*1713Smax.romanov@nginx.com } 134*1713Smax.romanov@nginx.com 135*1713Smax.romanov@nginx.com }(c_req, get_handler(uintptr(c_req.unit.data))) 1361316Smax.romanov@nginx.com} 137