xref: /unit/go/request.go (revision 1713:f5ba5973a0a3)
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