response.go (1323:6dfc9895e25e) response.go (1713:f5ba5973a0a3)
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 "net/http"
15)
16
17type response struct {
18 header http.Header
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 "net/http"
15)
16
17type response struct {
18 header http.Header
19 headerSent bool
20 req *http.Request
21 c_req C.uintptr_t
19 header_sent bool
20 c_req *C.nxt_unit_request_info_t
22 ch chan int
23}
24
21 ch chan int
22}
23
25func new_response(c_req C.uintptr_t, req *http.Request) *response {
26 resp := &response{
27 header: http.Header{},
28 req: req,
29 c_req: c_req,
30 }
31
32 return resp
33}
34
35func (r *response) Header() http.Header {
36 return r.header
37}
38
39func (r *response) Write(p []byte) (n int, err error) {
24func (r *response) Header() http.Header {
25 return r.header
26}
27
28func (r *response) Write(p []byte) (n int, err error) {
40 if !r.headerSent {
29 if !r.header_sent {
41 r.WriteHeader(http.StatusOK)
42 }
43
44 l := len(p)
45 written := int(0)
46 br := buf_ref(p)
47
48 for written < l {

--- 10 unchanged lines hidden (view full) ---

59 wait_shm_ack(r.ch)
60 }
61 }
62
63 return written, nil
64}
65
66func (r *response) WriteHeader(code int) {
30 r.WriteHeader(http.StatusOK)
31 }
32
33 l := len(p)
34 written := int(0)
35 br := buf_ref(p)
36
37 for written < l {

--- 10 unchanged lines hidden (view full) ---

48 wait_shm_ack(r.ch)
49 }
50 }
51
52 return written, nil
53}
54
55func (r *response) WriteHeader(code int) {
67 if r.headerSent {
68 // Note: explicitly using Stderr, as Stdout is our HTTP output.
56 if r.header_sent {
69 nxt_go_warn("multiple response.WriteHeader calls")
70 return
71 }
57 nxt_go_warn("multiple response.WriteHeader calls")
58 return
59 }
72 r.headerSent = true
60 r.header_sent = true
73
74 // Set a default Content-Type
75 if _, hasType := r.header["Content-Type"]; !hasType {
76 r.header.Add("Content-Type", "text/html; charset=utf-8")
77 }
78
79 fields := 0
80 fields_size := 0
81
82 for k, vv := range r.header {
83 for _, v := range vv {
84 fields++
85 fields_size += len(k) + len(v)
86 }
87 }
88
61
62 // Set a default Content-Type
63 if _, hasType := r.header["Content-Type"]; !hasType {
64 r.header.Add("Content-Type", "text/html; charset=utf-8")
65 }
66
67 fields := 0
68 fields_size := 0
69
70 for k, vv := range r.header {
71 for _, v := range vv {
72 fields++
73 fields_size += len(k) + len(v)
74 }
75 }
76
89 C.nxt_cgo_response_create(r.c_req, C.int(code), C.int(fields),
77 C.nxt_unit_response_init(r.c_req, C.uint16_t(code), C.uint32_t(fields),
90 C.uint32_t(fields_size))
91
92 for k, vv := range r.header {
93 for _, v := range vv {
78 C.uint32_t(fields_size))
79
80 for k, vv := range r.header {
81 for _, v := range vv {
94 C.nxt_cgo_response_add_field(r.c_req, str_ref(k), C.uint8_t(len(k)),
82 C.nxt_unit_response_add_field(r.c_req, str_ref(k), C.uint8_t(len(k)),
95 str_ref(v), C.uint32_t(len(v)))
96 }
97 }
98
83 str_ref(v), C.uint32_t(len(v)))
84 }
85 }
86
99 C.nxt_cgo_response_send(r.c_req)
87 C.nxt_unit_response_send(r.c_req)
100}
101
102func (r *response) Flush() {
88}
89
90func (r *response) Flush() {
103 if !r.headerSent {
91 if !r.header_sent {
104 r.WriteHeader(http.StatusOK)
105 }
106}
107
108var observer_registry_ observable
109
110func wait_shm_ack(c chan int) {
111 observer_registry_.attach(c)
112
113 _ = <-c
114}
115
116//export nxt_go_shm_ack_handler
92 r.WriteHeader(http.StatusOK)
93 }
94}
95
96var observer_registry_ observable
97
98func wait_shm_ack(c chan int) {
99 observer_registry_.attach(c)
100
101 _ = <-c
102}
103
104//export nxt_go_shm_ack_handler
117func nxt_go_shm_ack_handler() {
105func nxt_go_shm_ack_handler(ctx *C.nxt_unit_ctx_t) {
118 observer_registry_.notify(1)
119}
106 observer_registry_.notify(1)
107}