xref: /unit/go/response.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	"net/http"
151316Smax.romanov@nginx.com)
161316Smax.romanov@nginx.com
171316Smax.romanov@nginx.comtype response struct {
181316Smax.romanov@nginx.com	header     http.Header
19*1713Smax.romanov@nginx.com	header_sent bool
20*1713Smax.romanov@nginx.com	c_req      *C.nxt_unit_request_info_t
211323Smax.romanov@nginx.com	ch         chan int
221316Smax.romanov@nginx.com}
231316Smax.romanov@nginx.com
241316Smax.romanov@nginx.comfunc (r *response) Header() http.Header {
251316Smax.romanov@nginx.com	return r.header
261316Smax.romanov@nginx.com}
271316Smax.romanov@nginx.com
281316Smax.romanov@nginx.comfunc (r *response) Write(p []byte) (n int, err error) {
29*1713Smax.romanov@nginx.com	if !r.header_sent {
301316Smax.romanov@nginx.com		r.WriteHeader(http.StatusOK)
311316Smax.romanov@nginx.com	}
321316Smax.romanov@nginx.com
331323Smax.romanov@nginx.com	l := len(p)
341323Smax.romanov@nginx.com	written := int(0)
351323Smax.romanov@nginx.com	br := buf_ref(p)
361323Smax.romanov@nginx.com
371323Smax.romanov@nginx.com	for written < l {
381323Smax.romanov@nginx.com		res := C.nxt_cgo_response_write(r.c_req, br, C.uint32_t(l - written))
391323Smax.romanov@nginx.com
401323Smax.romanov@nginx.com		written += int(res)
411323Smax.romanov@nginx.com		br += C.uintptr_t(res)
421323Smax.romanov@nginx.com
431323Smax.romanov@nginx.com		if (written < l) {
441323Smax.romanov@nginx.com			if r.ch == nil {
451323Smax.romanov@nginx.com				r.ch = make(chan int, 2)
461323Smax.romanov@nginx.com			}
471323Smax.romanov@nginx.com
481323Smax.romanov@nginx.com			wait_shm_ack(r.ch)
491323Smax.romanov@nginx.com		}
501323Smax.romanov@nginx.com	}
511323Smax.romanov@nginx.com
521323Smax.romanov@nginx.com	return written, nil
531316Smax.romanov@nginx.com}
541316Smax.romanov@nginx.com
551316Smax.romanov@nginx.comfunc (r *response) WriteHeader(code int) {
56*1713Smax.romanov@nginx.com	if r.header_sent {
571316Smax.romanov@nginx.com		nxt_go_warn("multiple response.WriteHeader calls")
581316Smax.romanov@nginx.com		return
591316Smax.romanov@nginx.com	}
60*1713Smax.romanov@nginx.com	r.header_sent = true
611316Smax.romanov@nginx.com
621316Smax.romanov@nginx.com	// Set a default Content-Type
631316Smax.romanov@nginx.com	if _, hasType := r.header["Content-Type"]; !hasType {
641316Smax.romanov@nginx.com		r.header.Add("Content-Type", "text/html; charset=utf-8")
651316Smax.romanov@nginx.com	}
661316Smax.romanov@nginx.com
671316Smax.romanov@nginx.com	fields := 0
681316Smax.romanov@nginx.com	fields_size := 0
691316Smax.romanov@nginx.com
701316Smax.romanov@nginx.com	for k, vv := range r.header {
711316Smax.romanov@nginx.com		for _, v := range vv {
721316Smax.romanov@nginx.com			fields++
731316Smax.romanov@nginx.com			fields_size += len(k) + len(v)
741316Smax.romanov@nginx.com		}
751316Smax.romanov@nginx.com	}
761316Smax.romanov@nginx.com
77*1713Smax.romanov@nginx.com	C.nxt_unit_response_init(r.c_req, C.uint16_t(code), C.uint32_t(fields),
781316Smax.romanov@nginx.com		C.uint32_t(fields_size))
791316Smax.romanov@nginx.com
801316Smax.romanov@nginx.com	for k, vv := range r.header {
811316Smax.romanov@nginx.com		for _, v := range vv {
82*1713Smax.romanov@nginx.com			C.nxt_unit_response_add_field(r.c_req, str_ref(k), C.uint8_t(len(k)),
831316Smax.romanov@nginx.com				str_ref(v), C.uint32_t(len(v)))
841316Smax.romanov@nginx.com		}
851316Smax.romanov@nginx.com	}
861316Smax.romanov@nginx.com
87*1713Smax.romanov@nginx.com	C.nxt_unit_response_send(r.c_req)
881316Smax.romanov@nginx.com}
891316Smax.romanov@nginx.com
901316Smax.romanov@nginx.comfunc (r *response) Flush() {
91*1713Smax.romanov@nginx.com	if !r.header_sent {
921316Smax.romanov@nginx.com		r.WriteHeader(http.StatusOK)
931316Smax.romanov@nginx.com	}
941316Smax.romanov@nginx.com}
951323Smax.romanov@nginx.com
961323Smax.romanov@nginx.comvar observer_registry_ observable
971323Smax.romanov@nginx.com
981323Smax.romanov@nginx.comfunc wait_shm_ack(c chan int) {
991323Smax.romanov@nginx.com	observer_registry_.attach(c)
1001323Smax.romanov@nginx.com
1011323Smax.romanov@nginx.com	_ = <-c
1021323Smax.romanov@nginx.com}
1031323Smax.romanov@nginx.com
1041323Smax.romanov@nginx.com//export nxt_go_shm_ack_handler
105*1713Smax.romanov@nginx.comfunc nxt_go_shm_ack_handler(ctx *C.nxt_unit_ctx_t) {
1061323Smax.romanov@nginx.com	observer_registry_.notify(1)
1071323Smax.romanov@nginx.com}
108