summaryrefslogblamecommitdiffhomepage
path: root/src/go/unit/request.go
blob: 829a2c641d5b756fb879b2c9f5f10df4df017223 (plain) (tree)
1
2
3
4
5
6
7
8
9




                            
            

  
                        



          
            

                  
                


                     

                          
                         


                                                     
                                                                              
 



                                   



                                 
                                        


                  








                                                      



                                               
                                          

 

                                                 

 


                                                                    
 




                                                            
                        










                                                                                 


                      
                                         


                                 
                                                                     

                               
                                





                                                            

                                                                     
 
                                

                                                              


                                          
                                                                     
                                                        


                                
                                                                     
                                                                           


                               
                                                             
                                                               


                                       
                                                                            
 
                                                                                 
 










                                                        
/*
 * Copyright (C) Max Romanov
 * Copyright (C) NGINX, Inc.
 */

package unit

/*
#include "nxt_cgo_lib.h"
*/
import "C"

import (
	"io"
	"net/http"
	"net/url"
	"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_handler
func nxt_go_request_handler(go_req uintptr, h uintptr) {
	r := get_request(go_req)
	handler := *(*http.Handler)(unsafe.Pointer(h))

	go func(r *request) {
		handler.ServeHTTP(r.response(), &r.req)
		r.done()
	}(r)
}