summaryrefslogtreecommitdiff
path: root/ref/api/http.html
blob: b8db5c8c412a843cfb2024c5736dab070ab5edb0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
<!DOCTYPE HTML>
<html lang="en" class="light sidebar-visible" dir="ltr">
    <head>
        <!-- Book generated using mdBook -->
        <meta charset="UTF-8">
        <title>HTTP - NNG Reference Manual (DRAFT)</title>


        <!-- Custom HTML head -->

        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta name="theme-color" content="#ffffff">

        <link rel="icon" href="../favicon.svg">
        <link rel="shortcut icon" href="../favicon.png">
        <link rel="stylesheet" href="../css/variables.css">
        <link rel="stylesheet" href="../css/general.css">
        <link rel="stylesheet" href="../css/chrome.css">
        <link rel="stylesheet" href="../css/print.css" media="print">

        <!-- Fonts -->
        <link rel="stylesheet" href="../FontAwesome/css/font-awesome.css">
        <link rel="stylesheet" href="../fonts/fonts.css">

        <!-- Highlight.js Stylesheets -->
        <link rel="stylesheet" id="highlight-css" href="../highlight.css">
        <link rel="stylesheet" id="tomorrow-night-css" href="../tomorrow-night.css">
        <link rel="stylesheet" id="ayu-highlight-css" href="../ayu-highlight.css">

        <!-- Custom theme stylesheets -->
        <link rel="stylesheet" href="../theme/pagetoc.css">


        <!-- Provide site root and default themes to javascript -->
        <script>
            const path_to_root = "../";
            const default_light_theme = "light";
            const default_dark_theme = "navy";
            window.path_to_searchindex_js = "../searchindex.js";
        </script>
        <!-- Start loading toc.js asap -->
        <script src="../toc.js"></script>
    </head>
    <body>
    <div id="mdbook-help-container">
        <div id="mdbook-help-popup">
            <h2 class="mdbook-help-title">Keyboard shortcuts</h2>
            <div>
                <p>Press <kbd></kbd> or <kbd></kbd> to navigate between chapters</p>
                <p>Press <kbd>S</kbd> or <kbd>/</kbd> to search in the book</p>
                <p>Press <kbd>?</kbd> to show this help</p>
                <p>Press <kbd>Esc</kbd> to hide this help</p>
            </div>
        </div>
    </div>
    <div id="body-container">
        <!-- Work around some values being stored in localStorage wrapped in quotes -->
        <script>
            try {
                let theme = localStorage.getItem('mdbook-theme');
                let sidebar = localStorage.getItem('mdbook-sidebar');

                if (theme.startsWith('"') && theme.endsWith('"')) {
                    localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
                }

                if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
                    localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
                }
            } catch (e) { }
        </script>

        <!-- Set the theme before any content is loaded, prevents flash -->
        <script>
            const default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? default_dark_theme : default_light_theme;
            let theme;
            try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
            if (theme === null || theme === undefined) { theme = default_theme; }
            const html = document.documentElement;
            html.classList.remove('light')
            html.classList.add(theme);
            html.classList.add("js");
        </script>

        <input type="checkbox" id="sidebar-toggle-anchor" class="hidden">

        <!-- Hide / unhide sidebar before it is displayed -->
        <script>
            let sidebar = null;
            const sidebar_toggle = document.getElementById("sidebar-toggle-anchor");
            if (document.body.clientWidth >= 1080) {
                try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
                sidebar = sidebar || 'visible';
            } else {
                sidebar = 'hidden';
                sidebar_toggle.checked = false;
            }
            if (sidebar === 'visible') {
                sidebar_toggle.checked = true;
            } else {
                html.classList.remove('sidebar-visible');
            }
        </script>

        <nav id="sidebar" class="sidebar" aria-label="Table of contents">
            <!-- populated by js -->
            <mdbook-sidebar-scrollbox class="sidebar-scrollbox"></mdbook-sidebar-scrollbox>
            <noscript>
                <iframe class="sidebar-iframe-outer" src="../toc.html"></iframe>
            </noscript>
            <div id="sidebar-resize-handle" class="sidebar-resize-handle">
                <div class="sidebar-resize-indicator"></div>
            </div>
        </nav>

        <div id="page-wrapper" class="page-wrapper">

            <div class="page">
                <div id="menu-bar-hover-placeholder"></div>
                <div id="menu-bar" class="menu-bar sticky">
                    <div class="left-buttons">
                        <label id="sidebar-toggle" class="icon-button" for="sidebar-toggle-anchor" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
                            <i class="fa fa-bars"></i>
                        </label>
                        <button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
                            <i class="fa fa-paint-brush"></i>
                        </button>
                        <ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
                            <li role="none"><button role="menuitem" class="theme" id="default_theme">Auto</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="light">Light</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
                        </ul>
                        <button id="search-toggle" class="icon-button" type="button" title="Search (`/`)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="/ s" aria-controls="searchbar">
                            <i class="fa fa-search"></i>
                        </button>
                    </div>

                    <h1 class="menu-title">NNG Reference Manual (DRAFT)</h1>

                    <div class="right-buttons">
                        <a href="../print.html" title="Print this book" aria-label="Print this book">
                            <i id="print-button" class="fa fa-print"></i>
                        </a>

                    </div>
                </div>

                <div id="search-wrapper" class="hidden">
                    <form id="searchbar-outer" class="searchbar-outer">
                        <div class="search-wrapper">
                            <input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
                            <div class="spinner-wrapper">
                                <i class="fa fa-spinner fa-spin"></i>
                            </div>
                        </div>
                    </form>
                    <div id="searchresults-outer" class="searchresults-outer hidden">
                        <div id="searchresults-header" class="searchresults-header"></div>
                        <ul id="searchresults">
                        </ul>
                    </div>
                </div>

                <!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
                <script>
                    document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
                    document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
                    Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
                        link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
                    });
                </script>

                <div id="content" class="content">
                    <main>
                        <style>
.mdbook-alerts {
  padding: 8px 16px;
  margin-bottom: 16px;
  border-left: 0.25em solid var(--mdbook-alerts-color);
}

.mdbook-alerts > *:first-child {
  margin-top: 0;
}

.mdbook-alerts > *:last-child {
  margin-bottom: 0;
}

.mdbook-alerts-title {
  display: flex;
  font-weight: 600;
  align-items: center;
  line-height: 1;
  color: var(--mdbook-alerts-color);
  text-transform: capitalize;
}

.mdbook-alerts-icon {
  display: inline-block;
  width: 1em;
  height: 1em;
  margin-right: 0.2em;
  background-color: currentColor;
  -webkit-mask: no-repeat center / 100%;
  mask: no-repeat center / 100%;
  -webkit-mask-image: var(--mdbook-alerts-icon);
  mask-image: var(--mdbook-alerts-icon);
}

.mdbook-alerts-note {
  --mdbook-alerts-color: rgb(9, 105, 218);
  /* https://icon-sets.iconify.design/material-symbols/info-outline-rounded/ */
  --mdbook-alerts-icon: url('data:image/svg+xml,%3Csvg xmlns="http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg" width="24" height="24" viewBox="0 0 24 24"%3E%3Cpath fill="currentColor" d="M12 17q.425 0 .713-.288T13 16v-4q0-.425-.288-.712T12 11q-.425 0-.712.288T11 12v4q0 .425.288.713T12 17m0-8q.425 0 .713-.288T13 8q0-.425-.288-.712T12 7q-.425 0-.712.288T11 8q0 .425.288.713T12 9m0 13q-2.075 0-3.9-.788t-3.175-2.137q-1.35-1.35-2.137-3.175T2 12q0-2.075.788-3.9t2.137-3.175q1.35-1.35 3.175-2.137T12 2q2.075 0 3.9.788t3.175 2.137q1.35 1.35 2.138 3.175T22 12q0 2.075-.788 3.9t-2.137 3.175q-1.35 1.35-3.175 2.138T12 22m0-2q3.35 0 5.675-2.325T20 12q0-3.35-2.325-5.675T12 4Q8.65 4 6.325 6.325T4 12q0 3.35 2.325 5.675T12 20m0-8"%2F%3E%3C%2Fsvg%3E');
}

.mdbook-alerts-tip {
  --mdbook-alerts-color: rgb(26, 127, 55);
  /* https://icon-sets.iconify.design/material-symbols/lightbulb-outline-rounded/ */
  --mdbook-alerts-icon: url('data:image/svg+xml,%3Csvg xmlns="http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg" width="24" height="24" viewBox="0 0 24 24"%3E%3Cpath fill="currentColor" d="M12 22q-.825 0-1.412-.587T10 20h4q0 .825-.587 1.413T12 22m-3-3q-.425 0-.712-.288T8 18q0-.425.288-.712T9 17h6q.425 0 .713.288T16 18q0 .425-.288.713T15 19zm-.75-3q-1.725-1.025-2.738-2.75T4.5 9.5q0-3.125 2.188-5.312T12 2q3.125 0 5.313 2.188T19.5 9.5q0 2.025-1.012 3.75T15.75 16zm.6-2h6.3q1.125-.8 1.738-1.975T17.5 9.5q0-2.3-1.6-3.9T12 4Q9.7 4 8.1 5.6T6.5 9.5q0 1.35.613 2.525T8.85 14M12 14"%2F%3E%3C%2Fsvg%3E');
}

.mdbook-alerts-important {
  --mdbook-alerts-color: rgb(130, 80, 223);
  /* https://icon-sets.iconify.design/material-symbols/chat-info-outline-rounded/ */
  --mdbook-alerts-icon: url('data:image/svg+xml,%3Csvg xmlns="http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg" width="24" height="24" viewBox="0 0 24 24"%3E%3Cpath fill="currentColor" d="M12 7q.425 0 .713-.288T13 6q0-.425-.288-.712T12 5q-.425 0-.712.288T11 6q0 .425.288.713T12 7m0 8q.425 0 .713-.288T13 14v-4q0-.425-.288-.712T12 9q-.425 0-.712.288T11 10v4q0 .425.288.713T12 15m-6 3l-2.3 2.3q-.475.475-1.088.213T2 19.575V4q0-.825.588-1.412T4 2h16q.825 0 1.413.588T22 4v12q0 .825-.587 1.413T20 18zm-.85-2H20V4H4v13.125zM4 16V4z"%2F%3E%3C%2Fsvg%3E');
}

.mdbook-alerts-warning {
  --mdbook-alerts-color: rgb(154, 103, 0);
  /* https://icon-sets.iconify.design/material-symbols/warning-outline-rounded/ */
  --mdbook-alerts-icon: url('data:image/svg+xml,%3Csvg xmlns="http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg" width="24" height="24" viewBox="0 0 24 24"%3E%3Cpath fill="currentColor" d="M2.725 21q-.275 0-.5-.137t-.35-.363q-.125-.225-.137-.488t.137-.512l9.25-16q.15-.25.388-.375T12 3q.25 0 .488.125t.387.375l9.25 16q.15.25.138.513t-.138.487q-.125.225-.35.363t-.5.137zm1.725-2h15.1L12 6zM12 18q.425 0 .713-.288T13 17q0-.425-.288-.712T12 16q-.425 0-.712.288T11 17q0 .425.288.713T12 18m0-3q.425 0 .713-.288T13 14v-3q0-.425-.288-.712T12 10q-.425 0-.712.288T11 11v3q0 .425.288.713T12 15m0-2.5"%2F%3E%3C%2Fsvg%3E');
}

.mdbook-alerts-caution {
  --mdbook-alerts-color: rgb(207, 34, 46);
  /* https://icon-sets.iconify.design/material-symbols/brightness-alert-outline-rounded/ */
  --mdbook-alerts-icon: url('data:image/svg+xml,%3Csvg xmlns="http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg" width="24" height="24" viewBox="0 0 24 24"%3E%3Cpath fill="currentColor" d="M12 17q.425 0 .713-.288T13 16q0-.425-.288-.712T12 15q-.425 0-.712.288T11 16q0 .425.288.713T12 17m0-4q.425 0 .713-.288T13 12V8q0-.425-.288-.712T12 7q-.425 0-.712.288T11 8v4q0 .425.288.713T12 13m-3.35 7H6q-.825 0-1.412-.587T4 18v-2.65L2.075 13.4q-.275-.3-.425-.662T1.5 12q0-.375.15-.737t.425-.663L4 8.65V6q0-.825.588-1.412T6 4h2.65l1.95-1.925q.3-.275.663-.425T12 1.5q.375 0 .738.15t.662.425L15.35 4H18q.825 0 1.413.588T20 6v2.65l1.925 1.95q.275.3.425.663t.15.737q0 .375-.15.738t-.425.662L20 15.35V18q0 .825-.587 1.413T18 20h-2.65l-1.95 1.925q-.3.275-.662.425T12 22.5q-.375 0-.737-.15t-.663-.425zm.85-2l2.5 2.5l2.5-2.5H18v-3.5l2.5-2.5L18 9.5V6h-3.5L12 3.5L9.5 6H6v3.5L3.5 12L6 14.5V18zm2.5-6"%2F%3E%3C%2Fsvg%3E');
}

</style>
<h1 id="http-support"><a class="header" href="#http-support">HTTP Support</a></h1>
<p>NNG offers support for creation of HTTP clients, and servers. NNG supports HTTP/1.1 at present, and supports
a subset of functionality, but the support should be sufficient for simple clients, REST API servers, static content servers,
and gateways between HTTP and and other protocols. It also provides support for WebSocket based connections.</p>
<p>HTTP follows a request/reply model, where a client issues a request, and the server is expected to reply.
Every request is answered with a single reply.</p>
<h2 id="header-file"><a class="header" href="#header-file">Header File</a></h2>
<pre><code class="language-c">#include &lt;nng/http.h&gt;
</code></pre>
<p>Unlike the rest of NNG, the HTTP API in NNG requires including <code>nng/http.h</code>. It is not necessary to include
the main <code>nng/nng.h</code> header, it will be included transitively by <code>nng/http.h</code>.</p>
<h2 id="connection-object"><a class="header" href="#connection-object">Connection Object</a></h2>
<pre><code class="language-c">typedef struct nng_http nng_http;
</code></pre>
<p>The <a name="a001"></a><code>nng_http</code> object represents a single logical HTTP connection to the server.
For HTTP/1.1 and earlier, this will correspond to a single TCP connection, but the object
also contains state relating to the transaction, such as the hostname used, HTTP method used,
request headers, response status, response headers, and so forth.</p>
<p>An <code>nng_http</code> object can be reused, unless closed, so that additional transactions can be
performed after the first transaction is complete.</p>
<p>At any given point in time, an <code>nng_http</code> object can only refer to a single HTTP transaction.
In NNG, these <code>nng_http</code> objects are used in both the client and server APIs.</p>
<p>The <code>nng_http</code> object is created by either <a href="../../api/http.html#creating-connections"><code>nng_http_client_connect</code></a> or by an HTTP server
object which then passes it to an <a href="../../api/http.html#handlers"><code>nng_http_handler</code></a> callback function.</p>
<h3 id="http-method"><a class="header" href="#http-method">HTTP Method</a></h3>
<pre><code class="language-c">void nng_http_set_method(nng_http *conn, const char *method);
const char *nng_http_get_method(nng_http *conn);
</code></pre>
<p>Each HTTP transaction has a single verb, or method, that is used. The most common methods are “GET”, “HEAD”, and “POST”,
but a number of others are possible.</p>
<p>The <a name="a002"></a><code>nng_http_set_method</code> function specifies the HTTP method to use for the transaction.
The default is “GET”. HTTP methods are case sensitive, and generally upper-case, such as “GET”, “POST”, “HEAD”,
and so forth. This function silently truncates any method to 32-characters. (There are no defined methods longer than this.)</p>
<p>The <a name="a003"></a><code>nng_http_get_method</code> function is used, typically on a server, to retrieve the method the client
set when issuing the transaction.</p>
<h3 id="http-uri"><a class="header" href="#http-uri">HTTP URI</a></h3>
<pre><code class="language-c">nng_err nng_http_set_uri(nng_http *conn, const char *uri, const char *query);
const char *nng_http_get_uri(nng_http *conn);
</code></pre>
<p>The <a name="a004"></a><code>nng_http_set_uri</code> function sets the <a name="a005"></a>URI, which normally appears like a path such as “/docs/index.html”,
for the next transaction on <em>conn</em>. It sets the URI to <em>uri</em>, and, if <em>query</em> is not <code>NULL</code>, also appends the
contents of <em>query</em>, separated by either the ‘?’ or ‘&amp;’ character, depending on whether <em>uri</em> already
contains a query string. It may return <a href="../../api/errors.html#NNG_ENOMEM"><code>NNG_ENOMEM</code></a>, or <a href="../../api/errors.html#NNG_EMSGSIZE"><code>NNG_EMSGSIZE</code></a> if the the result is too long,
or <a href="../../api/errors.html#NNG_EINVAL"><code>NNG_EINVAL</code></a> if there is some other problem with the URI.</p>
<div class="mdbook-alerts mdbook-alerts-note">
<p class="mdbook-alerts-title">
  <span class="mdbook-alerts-icon"></span>
  note
</p>
<p>The <em>uri</em> and <em>query</em> must be already percent-encoded if necessary.</p>
</div>
<p>The <a name="a006"></a><code>nni_http_get_uri</code> function is used to obtain the URI that was previously set by <code>nng_http_set_uri</code>.
If the URI is unset (such as for a freshly created connection), then it returns <code>NULL</code>. The returned value
will have any query concatenated, for example “/api/get_user.cgi?name=garrett”.</p>
<h3 id="http-version"><a class="header" href="#http-version">HTTP Version</a></h3>
<pre><code class="language-c">nng_err nng_http_set_version(nng_http *conn, const char *version);
const char *nng_http_get_version(nng_http *conn);
</code></pre>
<p>The <a name="a007"></a><code>nng_http_set_version</code> function is used to select the HTTP protocol version to use for the
exchange. At present, only the values <code>NNG_HTTP_VERSION_1_0</code> and <code>NNG_HTTP_VERSION_1_1</code> (corresponding to
“HTTP/1.0” and “HTTP/1.1”) are supported. NNG will default to using “HTTP/1.1” if this function is not called.
If an unsupported version is supplied, <a href="../../api/errors.html#NNG_ENOTSUP"><code>NNG_ENOTSUP</code></a> will be returned, otherwise zero.</p>
<p>The <a name="a008"></a><code>nng_http_get_version</code> function is used to determine the version the client selected. Normally
there is little need to use this, but there are some subtle semantic differences between HTTP/1.0 and HTTP/1.1.</p>
<div class="mdbook-alerts mdbook-alerts-tip">
<p class="mdbook-alerts-title">
  <span class="mdbook-alerts-icon"></span>
  tip
</p>
<p>There are few, if any, remaining HTTP/1.0 implementations that are not also capable of HTTP/1.1.
It might be easiest to just fail any request coming in that is not HTTP/1.1.</p>
</div>
<div class="mdbook-alerts mdbook-alerts-note">
<p class="mdbook-alerts-title">
  <span class="mdbook-alerts-icon"></span>
  note
</p>
<p>NNG does not support HTTP/2 or HTTP/3 at this time.</p>
</div>
<h3 id="http-status"><a class="header" href="#http-status">HTTP Status</a></h3>
<pre><code class="language-c">typedef enum ... nng_http_status;
nng_http_status nng_http_get_status(nng_http *conn);
const char *nng_http_get_reason(nng_http_conn *conn);
void nng_http_set_status(nng_http *conn, nng_http_status status, const char *reason);
</code></pre>
<p>The <a name="a009"></a><code>nng_http_get_status</code> function obtains the numeric code (typipcally numbered from 100 through 599) returned
by the server in the last exchange on <em>conn</em>. (If no exchange has been performed yet, the result is undefined.)
The value is returned as an <a name="a010"></a><code>nng_http_status</code>.</p>
<p>A descriptive message matching the status code is returned by <a name="a011"></a><code>nng_http_get_reason</code>.</p>
<p>The <a name="a012"></a><code>nng_http_set_status</code> function is used on a server in a handler callback to set the status code that will be
reported to the client to <em>status</em>, and the associated text (reason) to <em>reason</em>. If <em>reason</em> is <code>NULL</code>,
then a built in reason based on the <em>status</em> will be used instead.</p>
<div class="mdbook-alerts mdbook-alerts-tip">
<p class="mdbook-alerts-title">
  <span class="mdbook-alerts-icon"></span>
  tip
</p>
<p>Callbacks used on the server may wish to use <a href="../../TODO.html"><code>nng_http_server_set_error</code></a> or <a href="../../TODO.html"><code>nng_http_server_set_redirect</code></a> instead of
<code>nng_http_set_status</code>, because those functions will also set the response body to a suitable HTML document
for display to users.</p>
</div>
<p>Status codes are defined by the IETF. Here are definitions that NNG provides for convenience:</p>
<div class="table-wrapper"><table><thead><tr><th>Name</th><th>Code</th><th>Reason Text</th><th>Notes</th></tr></thead><tbody>
<tr><td><code>NNG_HTTP_STATUS_CONTINUE</code><a name="NNG_HTTP_STATUS_CONTINUE"></a></td><td>100</td><td>Continue</td><td>Partial transfer, client may send body.</td></tr>
<tr><td><code>NNG_HTTP_STATUS_SWITCHING</code><a name="NNG_HTTP_STATUS_SWITCHING"></a></td><td>101</td><td>Switching Protocols</td><td>Used when upgrading or hijacking a connection.</td></tr>
<tr><td><code>NNG_HTTP_STATUS_PROCESSING</code><a name="NNG_HTTP_STATUS_PROCESSING"></a></td><td>102</td><td>Processing</td><td></td></tr>
<tr><td><code>NNG_HTTP_STATUS_OK</code><a name="NNG_HTTP_STATUS_OK"></a></td><td>200</td><td>OK</td><td>Successful result.</td></tr>
<tr><td><code>NNG_HTTP_STATUS_CREATED</code><a name="NNG_HTTP_STATUS_CREATED"></a></td><td>201</td><td>Created</td><td>Resource created successfully.</td></tr>
<tr><td><code>NNG_HTTP_STATUS_ACCEPTED</code><a name="NNG_HTTP_STATUS_ACCEPTED"></a></td><td>202</td><td>Created</td><td>Request accepted for future processing.</td></tr>
<tr><td><code>NNG_HTTP_STATUS_NOT_AUTHORITATIVE</code><a name="NNG_HTTP_STATUS_NOT_AUTHORITATIVE"></a></td><td>203</td><td>Not Authoritative</td><td>Request successful, but modified by proxy.</td></tr>
<tr><td><code>NNG_HTTP_STATUS_NO_CONTENT</code><a name="NNG_HTTP_STATUS_NO_CONTENT"></a></td><td>204</td><td>No Content</td><td>Request successful, no content returned.</td></tr>
<tr><td><code>NNG_HTTP_STATUS_RESET_CONTENT</code><a name="NNG_HTTP_STATUS_NO_CONTENT"></a></td><td>205</td><td>Reset Content</td><td>Request successful, client should reload content.</td></tr>
<tr><td><code>NNG_HTTP_STATUS_PARTIAL_CONTENT</code><a name="NNG_HTTP_STATUS_NO_CONTENT"></a></td><td>206</td><td>Partial Content</td><td>Response to a range request.</td></tr>
<tr><td><code>NNG_HTTP_STATUS_MULTI_STATUS</code><a name="NNG_HTTP_STATUS_MULTI_STATUS"></a></td><td>207</td><td>Multi-Status</td><td>Used with WebDAV.</td></tr>
<tr><td><code>NNG_HTTP_STATUS_ALREADY_REPORTED</code><a name="NNG_HTTP_STATUS_ALREADY_REPORTED"></a></td><td>208</td><td>Already Reported</td><td>Used with WebDAV.</td></tr>
<tr><td><code>NNG_HTTP_STATUS_IM_USED</code><a name="NNG_HTTP_STATUS_IM_USED"></a></td><td>226</td><td>IM Used</td><td>Used with delta encodings, rarely supported.</td></tr>
<tr><td><code>NNG_HTTP_STATUS_MULTIPLE_CHOICES</code><a name="NNG_HTTP_STATUS_MULTIPLE_CHOICES"></a></td><td>300</td><td>Multiple Choices</td><td>Multiple responses possible, client should choose.</td></tr>
<tr><td><code>NNG_HTTP_STATUS_MOVED_PERMANENTLY</code><a name="NNG_HTTP_STATUS_MOVED_PERMANENTLY"></a></td><td>301</td><td>Moved Permanently</td><td>Permanent redirection, may be saved by client.</td></tr>
<tr><td><code>NNG_HTTP_STATUS_FOUND</code><a name="NNG_HTTP_STATUS_FOUND"></a></td><td>302</td><td>Found</td><td>Temporary redirection, client may switch to GET.</td></tr>
<tr><td><code>NNG_HTTP_STATUS_SEE_OTHER</code><a name="NNG_HTTP_STATUS_SEE_OTHER"></a></td><td>303</td><td>See Other</td><td>Redirect, perhaps after a success POST or PUT.</td></tr>
<tr><td><code>NNG_HTTP_STATUS_NOT_MODIFIED</code><a name="NNG_HTTP_STATUS_NOT_MODIFIED"></a></td><td>304</td><td>Not Modified</td><td>Resource not modified, client may use cached version.</td></tr>
<tr><td><code>NNG_HTTP_STATUS_USE_PROXY</code><a name="NNG_HTTP_STATUS_USE_PROXY"></a></td><td>305</td><td>Use Proxy</td><td></td></tr>
<tr><td><code>NNG_HTTP_STATUS_TEMPORARY_REDIRECT</code><a name="NNG_HTTP_STATUS_TEMPORARY_REDIRECT"></a></td><td>307</td><td>Temporary Redirect</td><td>Temporary redirect, preserves method.</td></tr>
<tr><td><code>NNG_HTTP_STATUS_PERMANENT_REDIRECT</code><a name="NNG_HTTP_STATUS_PERMANENT_REDIRECT"></a></td><td>308</td><td>Permanent Redirect</td><td>Permanent redirect.</td></tr>
<tr><td><code>NNG_HTTP_STATUS_BAD_REQUEST</code><a name="NNG_HTTP_STATUS_BAD_REQUEST"></a></td><td>400</td><td>Bad Request</td><td>Generic problem with the request.</td></tr>
<tr><td><code>NNG_HTTP_STATUS_UNAUTHORIZED</code><a name="NNG_HTTP_STATUS_UNAUTHORIZED"></a></td><td>401</td><td>Unauthorized</td><td>Indicates a problem with authentication.</td></tr>
<tr><td><code>NNG_HTTP_STATUS_PAYMENT_REQUIRED</code><a name="NNG_HTTP_STATUS_PAYMENT_REQUIRED"></a></td><td>402</td><td>Payment Required</td><td></td></tr>
<tr><td><code>NNG_HTTP_STATUS_FORBIDDEN</code><a name="NNG_HTTP_STATUS_FORBIDDEN"></a></td><td>403</td><td>Forbidden</td><td>No permission to access resource.</td></tr>
<tr><td><code>NNG_HTTP_STATUS_NOT_FOUND</code><a name="NNG_HTTP_STATUS_NOT_FOUND"></a></td><td>404</td><td>Not Found</td><td>Resource does not exist.</td></tr>
<tr><td><code>NNG_HTTP_STATUS_METHOD_NOT_ALLOWED</code><a name="NNG_HTTP_STATUS_METHOD_NOT_ALLOWED"></a></td><td>405</td><td>Method Not Allowed</td><td>Resource does not support the method.</td></tr>
<tr><td><code>NNG_HTTP_STATUS_METHOD_NOT_ACCEPTABLE</code><a name="NNG_HTTP_STATUS_METHOD_NOT_ACCEPTABLE"></a></td><td>406</td><td>Not Acceptable</td><td>Could not satisfy accept requirements.</td></tr>
<tr><td><code>NNG_HTTP_STATUS_PROXY_AUTH_REQUIRED</code><a name="NNG_HTTP_STATUS_PROXY_AUTH_REQUIRED"></a></td><td>407</td><td>Proxy Authentication Required</td><td>Proxy requires authentication.</td></tr>
<tr><td><code>NNG_HTTP_STATUS_REQUEST_TIMEOUT</code><a name="NNG_HTTP_STATUS_REQUEST_TIMEOUT"></a></td><td>408</td><td>Request Timeout</td><td>Timed out waiting for request.</td></tr>
<tr><td><code>NNG_HTTP_STATUS_CONFLICT</code><a name="NNG_HTTP_STATUS_CONFLICT"></a></td><td>409</td><td>Conflict</td><td>Conflicting request.</td></tr>
<tr><td><code>NNG_HTTP_STATUS_GONE</code><a name="NNG_HTTP_STATUS_GONE"></a></td><td>410</td><td>Gone</td><td>Resource no longer exists.</td></tr>
<tr><td><code>NNG_HTTP_STATUS_LENGTH_REQUIRED</code><a name="NNG_HTTP_STATUS_LENGTH_REQUIRED"></a></td><td>411</td><td>Length Required</td><td>Missing Content-Length.</td></tr>
<tr><td><code>NNG_HTTP_STATUS_PRECONDITION_FAILED</code><a name="NNG_HTTP_STATUS_PRECONDITION_FAILED"></a></td><td>412</td><td>Precondition Failed</td><td></td></tr>
<tr><td><code>NNG_HTTP_STATUS_CONTENT_TOO_LARGE</code><a name="NNG_HTTP_STATUS_PAYLOAD_TOO_LARGE"></a></td><td>413</td><td>Content Too Large</td><td></td></tr>
<tr><td><code>NNG_HTTP_STATUS_URI_TOO_LONG</code><a name="NNG_HTTP_STATUS_URI_TOO_LONG"></a></td><td>414</td><td>URI Too Long</td><td></td></tr>
<tr><td><code>NNG_HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE</code><a name="NNG_HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE"></a></td><td>415</td><td>Unsupported Media Type</td><td></td></tr>
<tr><td><code>NNG_HTTP_STATUS_RANGE_NOT_SATISFIABLE</code><a name="NNG_HTTP_STATUS_RANGE_NOT_SATISFIABLE"></a></td><td>416</td><td>Range Not Satisfiable</td><td></td></tr>
<tr><td><code>NNG_HTTP_STATUS_EXPECTATION_FAILED</code><a name="NNG_HTTP_STATUS_EXPECTATION_FAILED"></a></td><td>417</td><td>Expectation Failed</td><td></td></tr>
<tr><td><code>NNG_HTTP_STATUS_TEAPOT</code><a name="NNG_HTTP_STATUS_TEAPOT"></a></td><td>418</td><td>I Am A Teapot</td><td>RFC 2324.</td></tr>
<tr><td><code>NNG_HTTP_STATUS_UNPROCESSABLE_ENTITY</code><a name="NNG_HTTP_STATUS_UNPROCESSABLE_ENTITY"></a></td><td>422</td><td>Unprocessable Entity</td><td></td></tr>
<tr><td><code>NNG_HTTP_STATUS_LOCKED</code><a name="NNG_HTTP_STATUS_LOCKED"></a></td><td>423</td><td>Locked</td><td></td></tr>
<tr><td><code>NNG_HTTP_STATUS_FAILED_DEPENDENCY</code><a name="NNG_HTTP_STATUS_FAILED_DEPENDENCY"></a></td><td>424</td><td>Failed Dependency</td><td></td></tr>
<tr><td><code>NNG_HTTP_STATUS_TOO_EARLY</code><a name="NNG_HTTP_STATUS_TOO_EARLY"></a></td><td>425</td><td>Too Early</td><td></td></tr>
<tr><td><code>NNG_HTTP_STATUS_UPGRADE_REQUIRED</code><a name="NNG_HTTP_STATUS_UPGRADE_REQUIRED"></a></td><td>426</td><td>Upgrade Required</td><td></td></tr>
<tr><td><code>NNG_HTTP_STATUS_PRECONDITION_REQUIRED</code><a name="NNG_HTTP_STATUS_PRECONDITION_REQUIRED"></a></td><td>428</td><td>Precondition Required</td><td></td></tr>
<tr><td><code>NNG_HTTP_STATUS_TOO_MANY_REQUESTS</code><a name="NNG_HTTP_STATUS_TOO_MANY_REQUESTS"></a></td><td>429</td><td>Too Many Requests</td><td></td></tr>
<tr><td><code>NNG_HTTP_STATUS_HEADERS_TOO_LARGE</code><a name="NNG_HTTP_STATUS_HEADERS_TOO_LARGE"></a></td><td>431</td><td>Headers Too Large</td><td></td></tr>
<tr><td><code>NNG_HTTP_STATUS_UNAVAIL_LEGAL_REASONS</code><a name="NNG_HTTP_STATUS_UNAVAIL_LEGAL_REASONS"></a></td><td>451</td><td>Unavailable For Legal Reasons</td><td></td></tr>
<tr><td><code>NNG_HTTP_STATUS_INTERNAL_SERVER_ERROR</code><a name="NNG_HTTP_STATUS_INTERNAL_SERVER_ERROR"></a></td><td>500</td><td>Internal Server Error</td><td></td></tr>
<tr><td><code>NNG_HTTP_STATUS_NOT_IMPLEMENTED</code><a name="NNG_HTTP_STATUS_NOT_IMPLEMENTED"></a></td><td>501</td><td>Not Implemented</td><td>Server does not implement method.</td></tr>
<tr><td><code>NNG_HTTP_STATUS_BAD_GATEWAY</code><a name="NNG_HTTP_STATUS_BAD_GATEWAY"></a></td><td>502</td><td>Bad Gateway</td><td></td></tr>
<tr><td><code>NNG_HTTP_STATUS_SERVICE_UNAVAILALE</code><a name="NNG_HTTP_STATUS_SERVICE_UNAVAILABLE"></a></td><td>503</td><td>Service Unavailable</td><td></td></tr>
<tr><td><code>NNG_HTTP_STATUS_GATEWAY_TIMEOUT</code><a name="NNG_HTTP_STATUS_GATEWAY_TIMEOUT"></a></td><td>504</td><td>Gateway TImeout</td><td></td></tr>
<tr><td><code>NNG_HTTP_STATUS_HTTP_VERSION_NOT_SUPP</code><a name="NNG_HTTP_STATUS_HTTP_VERSION_NOT_SUPP"></a></td><td>505</td><td>HTTP Version Not Supported</td><td></td></tr>
<tr><td><code>NNG_HTTP_STATUS_VARIANT_ALSO_NEGOTIATES</code><a name="NNG_HTTP_STATUS_VARIANT_ALSO_NEGOTIATES"></a></td><td>506</td><td>Variant Also Negotiates</td><td></td></tr>
<tr><td><code>NNG_HTTP_STATUS_INSUFFICIENT_STORAGE</code><a name="NNG_HTTP_STATUS_INSUFFICIENT_STORAGE"></a></td><td>507</td><td>Variant Also Negotiates</td><td></td></tr>
<tr><td><code>NNG_HTTP_STATUS_LOOP_DETECTED</code><a name="NNG_HTTP_STATUS_LOOP_DETECTED"></a></td><td>508</td><td>Loop Detected</td><td></td></tr>
<tr><td><code>NNG_HTTP_STATUS_NOT_EXTENDED</code><a name="NNG_HTTP_STATUS_NOT_EXTENDED"></a></td><td>510</td><td>Not Extended</td><td></td></tr>
<tr><td><code>NNG_HTTP_STATUS_NETWORK_AUTH_REQUIRED</code><a name="NNG_HTTP_STATUS_NETWORK_AUTH_REQUIRED"></a></td><td>511</td><td>Network Authentication Required</td><td></td></tr>
</tbody></table>
</div>
<h3 id="retrieving-headers"><a class="header" href="#retrieving-headers">Retrieving Headers</a></h3>
<pre><code class="language-c">const char *nng_http_get_header(nng_http *conn, const char *key);
bool nng_http_next_header(nng_http *conn, const char **keyp, const char **valuep, void **next);
</code></pre>
<p>The <a name="a013"></a><code>nng_http_get_header</code> returns the header value matching <em>key</em> that was received over <em>conn</em>,
or <code>NULL</code> if no such header exists.</p>
<p>Thus, if <em>conn</em> is a client connection, then this function returns the the header value
sent by the server as part of a response, whereas if it is a server connection, it returns
the header value sent by the client as part of the request.</p>
<p>If multiple headers are present with the same key, they may be returned as a combined value,
with individual values separated by commas, but this behavior is not guaranteed.</p>
<p>The <a name="a014"></a><code>nng_http_next_header</code> function iterates over all the headers, using the same list
that <code>nng_http_get_header</code> uses. To start, it is called with <em>next</em> initialized to <code>NULL</code>.
If a header was found, then it returns <code>true</code>, and sets <em>keyp</em> and <em>valuep</em> to values containing
the header name and value. It also updates <em>next</em>, which should be used for the next iteration.</p>
<p>Once <code>nng_http_next_header</code> returns <code>false</code>, further calls with the same parameters will continue to do so.
The scan can be rest by setting <em>next</em> to <code>NULL</code>.</p>
<h3 id="modifying-headers"><a class="header" href="#modifying-headers">Modifying Headers</a></h3>
<pre><code class="language-c">nng_err nng_http_add_header(nng_http *conn, const char *key, const char *val);
nng_err nng_http_set_header(nng_http *conn, const char *key, const char *val);
void nng_http_del_header(nng_http *conn, const char *key);
</code></pre>
<p>The <a name="a015"></a><code>nng_http_add_header</code>, <a name="a016"></a><code>nng_http_set_header</code>, and <a name="a017"></a><code>nng_http_del_header</code> functions are
used to add a modify either the request or response headers for <em>conn</em> prior to sending to the connected peer on <em>conn</em>.</p>
<p>Thus, if the <em>conn</em> is a client connection created by <a href="../../api/http.html#creating-connections"><code>nng_http_client_connect</code></a>, then the request headers are modified.
Conversely, if it is a connection created by an HTTP server and used in a callback function, then the response headers are modified.</p>
<p>The <code>nng_http_add_header</code> function adds a header with the name <em>key</em>, and the value <em>val</em>, to the list of headers.
In so doing, it may bring collapse multiple headers with the same name into a comma separated list, following
the syntax specified in RFC 9110. The function may return <a href="../../api/errors.html#NNG_ENOMEM"><code>NNG_ENOMEM</code></a>, <a href="../../api/errors.html#NNG_EMSGSIZE"><code>NNG_EMSGSIZE</code></a>, or <a href="../../api/errors.html#NNG_EINVAL"><code>NNG_EINVAL</code></a>.</p>
<p>The <code>nng_http_set_header</code> function adds the header if it does not already exist, but replaces any and all previously existing
headers with the same name <em>key</em>, if they exist. In all other respects it behaves similarly to <code>nng_http_add_header</code>.</p>
<p>The <code>nng_http_del_header</code> removes all headers with name <em>key</em>.</p>
<div class="mdbook-alerts mdbook-alerts-note">
<p class="mdbook-alerts-title">
  <span class="mdbook-alerts-icon"></span>
  note
</p>
<p>Some HTTP headers have special semantics, such as the “Host”, “Content-Length”, and “Content-Type” headers.
This implementation may apply those semantics, in order to conform to the specifications for HTTP, such
as by guaranting that only a single instance of one of these headers is present.</p>
</div>
<h3 id="retrieving-body-content"><a class="header" href="#retrieving-body-content">Retrieving Body Content</a></h3>
<pre><code class="language-c">void nng_http_get_body(nng_http_conn *conn, void **datap, size_t *sizep);
</code></pre>
<p>The <a name="a018"></a><code>nng_http_get_data</code> obtains the most recently received request or
response body. This will be <code>NULL</code> if the content has not been retrieved
properly yet, or if the peer did not any content. (Some requests are defined
to never have body content, such as “HEAD”.)</p>
<h3 id="storing-body-content"><a class="header" href="#storing-body-content">Storing Body Content</a></h3>
<pre><code class="language-c">void nng_http_set_body(nng_http_conn *conn, void *data, size_t size);
void nng_http_copy_body(nng_http_conn *conn, const void *data, size_t size);
</code></pre>
<p>The <a name="a019"></a><code>nng_http_set_body</code> function sets the outgoing body content to <em>data</em>,
which must be <em>size</em> bytes long. The caller must ensure that <em>data</em> remains
valid for the duration of the transaction.</p>
<p>The <a name="a020"></a><code>nng_http_copy_body</code> function makes a copy of <em>data</em>, which
will be freed automatically when the transaction is finished, but otherwise
behaves like <code>nng_http_set_body</code>.</p>
<p>On client <em>conn</em> objects, these functions update the request object, but on server
<em>conn</em> objects, they update the response object.</p>
<p>These functions also update the relevant “Content-Length” header.</p>
<div class="mdbook-alerts mdbook-alerts-note">
<p class="mdbook-alerts-title">
  <span class="mdbook-alerts-icon"></span>
  note
</p>
<p>The current framework does not support sending data via chunked
transfer-encoding.</p>
</div>
<div class="mdbook-alerts mdbook-alerts-tip">
<p class="mdbook-alerts-title">
  <span class="mdbook-alerts-icon"></span>
  tip
</p>
<p>It is a good idea to also set the <code>Content-Type</code> header.</p>
</div>
<h3 id="closing-the-connection"><a class="header" href="#closing-the-connection">Closing the Connection</a></h3>
<pre><code class="language-c">void nng_http_close(nng_http *conn);
</code></pre>
<p>The <a name="a021"></a><code>nng_http_close</code> function closes the supplied HTTP connection <em>conn</em>,
including any disposing of any underlying file descriptors or related resources.</p>
<p>Once this function, no further access to the <em>conn</em> structure may be made.</p>
<h3 id="reset-connection-state"><a class="header" href="#reset-connection-state">Reset Connection State</a></h3>
<pre><code class="language-c">void nng_http_reset(nng_http *conn);
</code></pre>
<p>The <a name="a022"></a><code>nng_http_reset</code> function resets the request and response state of the
the connection <em>conn</em>, so that it is just as if it had been freshly created with
<a href="../../api/http.html#creating-connections"><code>nng_http_client_connect</code></a> or passed into a handler function for a server callback.</p>
<p>The intended purpose of this function is to clear the object state before reusing the <em>conn</em> for
subsequent transactions.</p>
<h3 id="direct-read-and-write"><a class="header" href="#direct-read-and-write">Direct Read and Write</a></h3>
<pre><code class="language-c">void nng_http_read(nng_http *conn, nng_aio *aio);
void nng_http_write(nng_http *conn, nng_aio *aio);
void nng_http_read_all(nng_http *conn, nng_aio *aio);
void nng_http_write_all(nng_http *conn, nng_aio *aio);
</code></pre>
<p>The <a name="a023"></a><code>nng_http_read</code> and <a name="a024"></a><code>nng_http_write</code> functions read or write data asynchronously from or to the
connection <em>conn</em>, using the <a href="../../api/aio.html#scatter-gather-vectors"><code>nng_iov</code></a> that is set in <em>aio</em> with <a href="../../api/aio.html#scatter-gather-vectors"><code>nng_aio_set_iov</code></a>.
These functions will complete as soon as any data is transferred.
Use <a href="../../api/aio.html#result-of-operation"><code>nng_aio_count</code></a> to determine how much data was actually transferred.</p>
<p>The <a name="a025"></a><code>nng_http_read_all</code> and <a name="a026"></a><code>nng_http_write_all</code> functions perform the same task, but will keep resubmitting
operations until the the entire amount of data requested by the <a href="../../api/aio.html#scatter-gather-vectors"><code>nng_iov</code></a> is transferred.</p>
<div class="mdbook-alerts mdbook-alerts-note">
<p class="mdbook-alerts-title">
  <span class="mdbook-alerts-icon"></span>
  note
</p>
<p>These functions perform no special handling for chunked transfers.</p>
</div>
<p>These functions are most likely to be useful after hijacking the connection with <a href="../../api/http.html#hijacking-connections"><code>nng_http_hijack</code></a>.
They can be used to transfer request or response body data as well.</p>
<h3 id="hijacking-connections"><a class="header" href="#hijacking-connections">Hijacking Connections</a></h3>
<pre><code class="language-c">nng_err nng_http_hijack(nng_http *conn);
</code></pre>
<p>TODO: This API will change to convert the conn into a stream object.</p>
<p>The <a name="a027"></a><code>nng_http_hijack</code> function hijacks the connection <em>conn</em>, causing it
to be disassociated from the HTTP server where it was created.</p>
<p>The purpose of this function is the creation of HTTP upgraders (such as
WebSocket), where the underlying HTTP connection will be taken over for
some other purpose, and should not be used any further by the server.</p>
<p>This function is most useful when called from a handler function.
(See <a href="../../api/http.html#handlers"><code>nng_http_handler_alloc</code></a>.)</p>
<div class="mdbook-alerts mdbook-alerts-note">
<p class="mdbook-alerts-title">
  <span class="mdbook-alerts-icon"></span>
  note
</p>
<p>It is the responsibility of the caller to dispose of the underlying connection when it is no longer needed.
Furthermore, the HTTP server will no longer send any responses to the hijacked connection, so the caller should do that as well if appropriate.
(See <a href="../../api/http.html#sending-the-response-explicitly"><code>nng_http_write_response</code></a>.)</p>
</div>
<div class="mdbook-alerts mdbook-alerts-tip">
<p class="mdbook-alerts-title">
  <span class="mdbook-alerts-icon"></span>
  tip
</p>
<p>This function is intended to facilitate uses cases that involve changing the protocol from HTTP, such as WebSocket.
Most applications will never need to use this function.</p>
</div>
<h3 id="obtaining-tls-connection-details"><a class="header" href="#obtaining-tls-connection-details">Obtaining TLS Connection Details</a></h3>
<pre><code class="language-c">nng_err nng_http_peer_cert(nng_http_conn *conn, nng_tls_cert **certp);
</code></pre>
<p>TODO: We need to document the cert API.</p>
<p>The <a name="a028"></a><code>nng_http_peer_cert</code> function will obtain the TLS certificate object for the peer, if one is available.
This can then be used for additional authentication or identity specific logic.</p>
<p>The certificate must be released with [<code>nng_tls_cert_free</code>] when no longer in use.
See <a href="../../TODO.html"><code>nng_tls_cert</code></a> for more information about working with TLS certificates.</p>
<div class="mdbook-alerts mdbook-alerts-note">
<p class="mdbook-alerts-title">
  <span class="mdbook-alerts-icon"></span>
  note
</p>
<p>While it should be obvious that this function is only available when using HTTPS,
it also requires that peer authentication is in use, and may require that the underlying
TLS engine support peer certificate colleciton. (Some minimal configurations elide this
to save space in embedded environments.)</p>
</div>
<h2 id="client-api"><a class="header" href="#client-api">Client API</a></h2>
<p>The NNG client API consists of an API for creating connections, and an API for performing
transactions on those connections.</p>
<h3 id="client-object"><a class="header" href="#client-object">Client Object</a></h3>
<pre><code class="language-c">typedef struct nng_http_client nng_http_client;
</code></pre>
<p>The <a name="a029"></a><code>nng_http_client</code> object is the client side creator for <a href="../../api/http.html#connection-object"><code>nng_http</code></a> objects.
It is analogous to a <a href="../../TODO.html">dialer</a> object used elsewhere in NNG, but it specifically is only for HTTP.</p>
<h3 id="create-a-client"><a class="header" href="#create-a-client">Create a Client</a></h3>
<pre><code class="language-c">void nng_http_client_alloc(nng_http_client *clientp, const nng_url *url);
</code></pre>
<p>The <a name="a030"></a><code>nng_http_client_alloc</code> allocates an HTTP client suitable for
connecting to the server identified by <em>url</em> and stores a pointer to
it in the location referenced by <em>clientp</em>.</p>
<h3 id="destroy-a-client"><a class="header" href="#destroy-a-client">Destroy a Client</a></h3>
<pre><code class="language-c">void nng_http_client_free(nng_http_client *client);
</code></pre>
<p>The <a name="a031"></a><code>nng_http_client_free</code> connection destroys the client object and any
of its resources.</p>
<div class="mdbook-alerts mdbook-alerts-note">
<p class="mdbook-alerts-title">
  <span class="mdbook-alerts-icon"></span>
  note
</p>
<p>Any connections created by <a href="../../api/http.html#creating-connections"><code>nng_http_client_connect</code></a> are not affected by this function,
and must be closed explicitly as needed.</p>
</div>
<h3 id="client-tls"><a class="header" href="#client-tls">Client TLS</a></h3>
<pre><code class="language-c">nng_err nng_http_client_get_tls(nng_http_client *client, nng_tls_config **tlsp);
nng_err nng_http_client_set_tls(nng_http_client *client, nng_tls_config *tls);
</code></pre>
<p>The <a name="a032"></a><code>nng_http_client_get_tls</code> and <a name="a033"></a><code>nng_http_client_set_tls</code> functions are used to
retrieve or change the <a href="../../TODO.html">TLS configuration</a> used when making outbound connections, enabling
<a name="a034"></a>TLS as a result.</p>
<p>If TLS has not been previously configured on <em>client</em>, then <code>nng_http_client_get_tls</code> will return <a href="../../api/errors.html#NNG_EINVAL"><code>NNG_EINVAL</code></a>.
Both functions will return <a href="../../api/errors.html#NNG_ENOTSUP"><code>NNG_ENOTSUP</code></a> if either HTTP or TLS is not supported.</p>
<p>Calling <code>nng_http_client_set_tls</code> invalidates any client previously obtained with
<code>nng_http_client_get_tls</code>, unless a separate hold on the object was obtained.</p>
<p>Once TLS is enabled for an <code>nng_http_client</code>, it is not possible to disable TLS.</p>
<div class="mdbook-alerts mdbook-alerts-note">
<p class="mdbook-alerts-title">
  <span class="mdbook-alerts-icon"></span>
  note
</p>
<p>The TLS configuration itself cannot be changed once it has been used to create a connection,
such as by calling <a href="../../api/http.html#creating-connections"><code>nng_http_client_connect</code></a>, but a new one can be installed in the client.
Existing connections will use the TLS configuration that there were created with.</p>
</div>
<h3 id="creating-connections"><a class="header" href="#creating-connections">Creating Connections</a></h3>
<pre><code class="language-c">#include &lt;nng/http.h&gt;

void nng_http_client_connect(nng_http_client *client, nng_aio *aio);
</code></pre>
<p>The <a name="a035"></a><code>nng_http_client_connect</code> function makes an outgoing connection to the
server configured for <em>client</em>, and creates an <a href="../../api/http.html#connection-object"><code>nng_http</code></a> object for the connection.</p>
<p>This is done asynchronously, and when the operation succeseds the connection may be
retried from the <em>aio</em> using <a href="../../api/aio.html#inputs-and-outputs"><code>nng_aio_get_output</code></a> with index 0.</p>
<h4 id="example-1-connecting-to-google"><a class="header" href="#example-1-connecting-to-google">Example 1: Connecting to Google</a></h4>
<pre><code class="language-c">nng_aio *aio;
nng_url *url;
nng_http_client *client;
nng_http *conn;
nng_err rv;

// Error checks elided for clarity.
nng_url_parse(&amp;url, "http://www.google.com");
nng_aio_alloc(&amp;aio, NULL, NULL);
nng_http_client_alloc(&amp;client, url);

nng_http_client_connect(client, aio);

// Wait for connection to establish (or attempt to fail).
nng_aio_wait(aio);

if ((rv = nng_aio_result(aio)) != 0) {
    printf("Connection failed: %s\n", nng_strerror(rv));
} else {
    // Connection established, get it.
    conn = nng_aio_get_output(aio, 0);

    // ... do something with it here

    // Close the connection when done to avoid leaking it.
    nng_http_close(conn);
}
</code></pre>
<h3 id="preparing-a-transaction"><a class="header" href="#preparing-a-transaction">Preparing a Transaction</a></h3>
<h3 id="sending-the-request"><a class="header" href="#sending-the-request">Sending the Request</a></h3>
<pre><code class="language-c">void nng_http_write_request(nng_http *conn, nng_aio *aio);
</code></pre>
<p>The <a name="a036"></a><code>nng_http_write_request</code> function starts an asynchronous write of
the HTTP request associated with <em>conn</em>.
The entire request is sent,
including headers, and if present, the request body data.
(The request body can be set with
<a href="../../api/http.html#storing-body-content"><code>nng_http_set_body</code></a> or <a href="../../api/http.html#storing-body-content"><code>nng_http_copy_body</code></a>.)</p>
<p>This function returns immediately, with no return value.
Completion of the operation is signaled via the <em>aio</em>, and the final result
may be obtained via <a href="../../api/aio.html#result-of-operation"><code>nng_aio_result</code></a>.</p>
<div class="mdbook-alerts mdbook-alerts-tip">
<p class="mdbook-alerts-title">
  <span class="mdbook-alerts-icon"></span>
  tip
</p>
<p>Consider using the <a href="../../api/http.html#submitting-the-transaction"><code>nng_http_transact</code></a> function,
which provides a simpler interface for performing a complete HTTP client transaction.</p>
</div>
<h3 id="obtaining-the-response"><a class="header" href="#obtaining-the-response">Obtaining the Response</a></h3>
<pre><code class="language-c">void nng_http_read_response(nng_http *conn, nng_aio *aio);
</code></pre>
<p>The <a name="a037"></a><code>nng_http_read_response</code> function starts an asynchronous read from the
HTTP connection <em>conn</em>, reading an HTTP response into the response associated with <em>conn</em>, including all
of the related headers.</p>
<p>It does <em>not</em> transfer any response body. To do that, use <a href="../../api/http.html#direct-read-and-write"><code>nng_http_read_all</code></a> or <a href="../../api/http.html#direct-read-and-write"><code>nng_http_read</code></a>.</p>
<div class="mdbook-alerts mdbook-alerts-note">
<p class="mdbook-alerts-title">
  <span class="mdbook-alerts-icon"></span>
  note
</p>
<p>At this time we have no API support for reading chunked transfers directly. Applications that
need to do so may use the direct read functions.</p>
</div>
<div class="mdbook-alerts mdbook-alerts-tip">
<p class="mdbook-alerts-title">
  <span class="mdbook-alerts-icon"></span>
  tip
</p>
<p>An easier one-shot method for many use cases might be <a href="../../api/http.html#submitting-the-transaction"><code>nng_http_transact</code></a>.</p>
</div>
<h3 id="submitting-the-transaction"><a class="header" href="#submitting-the-transaction">Submitting the Transaction</a></h3>
<pre><code class="language-c">void nng_http_transact(nng_http *conn, nng_aio *aio);
</code></pre>
<p>The HTTP request is issued, and the response processed, asynchronously by the <a name="a038"></a><code>nng_http_transact</code> function.
When the function is complete, the <em>aio</em> will be notified.</p>
<p>The <a name="a039"></a><code>nng_http_transact</code> function is used to perform a complete
HTTP exchange over the connection <em>conn</em>, sending the request
and attached body data to the remote server, and reading the response.</p>
<p>The entire response is read, including any associated body, which can
subsequently be obtained using <a href="../../api/http.html#retrieving-body-content"><code>nng_http_get_body</code></a>.</p>
<p>This function is intended to make creation of client applications easier,
by performing multiple asynchronous operations required to complete an
entire HTTP transaction.</p>
<p>If an error occurs, the caller should close <em>conn</em> with <a href="../../api/http.html#closing-the-connection"><code>nng_http_close</code></a>, as it may not
necessarily be usable with other transactions.</p>
<div class="mdbook-alerts mdbook-alerts-warning">
<p class="mdbook-alerts-title">
  <span class="mdbook-alerts-icon"></span>
  warning
</p>
<p>If the remote server tries to send an extremely large buffer,
then a corresponding allocation will be made, which can lead to denial
of service attacks.
Client applications should take care to use this only with reasonably
trust-worthy servers.</p>
</div>
<div class="mdbook-alerts mdbook-alerts-note">
<p class="mdbook-alerts-title">
  <span class="mdbook-alerts-icon"></span>
  note
</p>
<p>A given connection <em>conn</em> should be used with only one
operation or transaction at a time as HTTP/1.1 has no support for
request interleaving.</p>
</div>
<p>This function returns immediately, with no return value.
Completion of the operation is signaled via the <em>aio</em>, and the final result
may be obtained via <a href="../../api/aio.html#result-of-operation"><code>nng_aio_result</code></a>.</p>
<h3 id="response-body"><a class="header" href="#response-body">Response Body</a></h3>
<h2 id="server-api"><a class="header" href="#server-api">Server API</a></h2>
<h3 id="handlers"><a class="header" href="#handlers">Handlers</a></h3>
<pre><code class="language-c">typedef struct nng_http_handler nng_http_handler;
</code></pre>
<p>An <a name="a040"></a><code>nng_http_handler</code> encapsulates a function used used to handle
incoming requests on an HTTP server, routed based on method and URI,
and the parameters used with that function.</p>
<p>Every handler has a Request-URI to which it refers, which is determined by the <em>path</em> argument.
Only the path component of the Request URI is considered when determining whether the handler should be called.</p>
<p>This implementation limits the <em>path</em> length to 1024 bytes, including the
zero termination byte. This does not prevent requests with much longer
URIs from being supported, but doing so will require setting the handler to match a parent path in the tree using
<a href="../../api/http.html#handling-an-entire-tree"><code>nng_http_handler_set_tree</code></a>.</p>
<div class="mdbook-alerts mdbook-alerts-tip">
<p class="mdbook-alerts-title">
  <span class="mdbook-alerts-icon"></span>
  tip
</p>
<p>The NNG HTTP framework is optimized for URLs shorter than 200 characters.</p>
</div>
<p>Additionally each handler has a method it is registered to handle
(the default is “GET” andc can be changed with <a href="../../api/http.html#setting-the-method"><code>nng_http_handler_set_method</code></a>), and
optionally a “Host” header it can be matched against (see <a href="../../api/http.html#filtering-byt-host"><code>nng_http_handler_set_host</code></a>).</p>
<p>In some cases, a handler may reference a logical tree rather (directory)
rather than just a single element.
(See <a href="../../api/http.html#handling-an-entire-tree"><code>nng_http_handler_set_tree</code></a>).</p>
<h3 id="implementing-a-handler"><a class="header" href="#implementing-a-handler">Implementing a Handler</a></h3>
<pre><code class="language-c">typedef void (*nng_http_handler_func)(nng_http_conn *conn, void *arg, nng_aio *aio);

nng_err nng_http_handler_alloc(nng_http_handler **hp, const char *path, nng_http_handler_func cb);
</code></pre>
<p>The <a name="a041"></a><code>nng_http_handler_alloc</code> function allocates a generic handler
which will be used to process requests coming into an HTTP server.
On success, a pointer to the handler is stored at the located pointed to by <em>hp</em>.</p>
<p>The handler function is specified by <em>cb</em>.
This function uses the asynchronous I/O framework.</p>
<p>The function receives the connection on <em>conn</em>, and an optional data pointer that was set
previously with <a href="../../api/http.html#setting-the-callback-argument"><code>nng_http_handler_set_data</code></a> as the second argument. The
final argument is the <a href="../../api/aio.html#asynchronous-io-handle"><code>nng_aio</code></a> <em>aio</em>, which must be “finished” to complete the operation.</p>
<p>The handler may call <a href="../../api/http.html#sending-the-response-explicitly"><code>nng_http_write_response</code></a> to send the response, or
it may simply let the framework do so on its behalf. The server will perform
this step if the callback has not already done so.</p>
<p>Response headers may be set using <a href="../../api/http.html#modifying-headers"><code>nng_http_set_header</code></a>, and request headers
may be accessed by using <a href="../../api/http.html#retrieving-headers"><code>nng_http_get_header</code></a>. They can also be iterated
over using <a href="../../api/http.html#retrieving-headers"><code>nng_http_next_header</code></a></p>
<p>Likewise the request body may be accessed, using <a href="../../api/http.html#retrieving-body-content"><code>nng_http_get_body</code></a>, and
the response body may be set using either <a href="../../api/http.html#storing-body-content"><code>nng_http_set_body</code></a> or <a href="../../api/http.html#storing-body-content"><code>nng_http_copy_body</code></a>.</p>
<div class="mdbook-alerts mdbook-alerts-note">
<p class="mdbook-alerts-title">
  <span class="mdbook-alerts-icon"></span>
  note
</p>
<p>The request body is only collected for the handler if the
<a href="../../api/http.html#collecting-request-body"><code>nng_http_handler_collect_body</code></a> function has been called for the handler.</p>
</div>
<p>The HTTP status should be set for the transaction using <a href="../../api/http.html#http-status"><code>nng_http_set_status</code></a>.</p>
<p>Finally, the handler should finish the operation by calling the <a href="../../TODO.html"><code>nng_aio_finish</code></a> function
after having set the status to <a href="../../api/errors.html#NNG_OK"><code>NNG_OK</code></a>.
If any other status is set on the <em>aio</em>, then a generic 500 response will be created and
sent, if possible, and the connection will be closed.</p>
<p>The <em>aio</em> may be scheduled for deferred completion using the <a href="../../TODO.html"><code>nng_aio_start</code></a>.</p>
<h3 id="serving-directories-and-files"><a class="header" href="#serving-directories-and-files">Serving Directories and Files</a></h3>
<pre><code class="language-c">nng_err nng_http_handler_alloc_directory(nng_http_handler **hp, const char *path, const char *dirname);
nng_err nng_http_handler_alloc_file(nng_http_handler **hp, const char *path, const char *filename);
</code></pre>
<p>The <a name="a042"></a><code>nng_http_handler_alloc_directory</code> and <a name="a043"></a><code>nng_http_handler_alloc_file</code>
create handlers pre-configured to act as static content servers for either a full
directory at <em>dirname</em>, or the single file at <em>filename</em>. These support the “GET” and “HEAD”
methods, and the directory variant will dynamically generate <code>index.html</code> content based on
the directory contents. These will also set the “Content-Type” if the file extension
matches one of the built-in values already known. If the no suitable MIME type can be
determined, the content type is set to “application/octet-stream”.</p>
<h3 id="static-handler"><a class="header" href="#static-handler">Static Handler</a></h3>
<pre><code class="language-c">nng_err nng_http_handler_alloc_static(nng_http_handler **hp, const char *path,
        const void *data, size_t size, const char *content_type);
</code></pre>
<p>The <a name="a044"></a><code>nng_http_handler_alloc_static</code> function creates a handler that
serves the content located in <em>data</em> (consisting of <em>size</em> bytes) at the URI <em>path</em>.
The <em>content_type</em> determines the “Content-Type” header. If <code>NULL</code> is specified
then a value of <code>application/octet-stream</code> is assumed.</p>
<h3 id="redirect-handler"><a class="header" href="#redirect-handler">Redirect Handler</a></h3>
<pre><code class="language-c">nng_err nng_http_handler_alloc_redirect(nng_http_handler **hp, const char *path,
        nng_http_status status, const char *location);
</code></pre>
<p>The <a name="a045"></a><code>nng_http_handler_alloc_redirect</code> function creates a handler with
a function that simply directions from the URI at <em>path</em> to the given <em>location</em>.</p>
<p>The HTTP reply it creates will be with <a href="../../api/http.html#http-status">status code</a> <em>status</em>,
which should be a 3XX code such as 301, and a <code>Location:</code> header will contain the URL
referenced by <em>location</em>, with any residual suffix from the request
URI appended.</p>
<div class="mdbook-alerts mdbook-alerts-tip">
<p class="mdbook-alerts-title">
  <span class="mdbook-alerts-icon"></span>
  tip
</p>
<p>Use <a href="../../api/http.html#handling-an-entire-tree"><code>nng_http_handler_set_tree</code></a> to redirect an entire tree.
For example, it is possible to redirect an entire HTTP site to another
HTTPS site by specifying <code>/</code> as the path and then using the base
of the new site, such as <code>https://newsite.example.com</code> as the new location.</p>
</div>
<div class="mdbook-alerts mdbook-alerts-tip">
<p class="mdbook-alerts-title">
  <span class="mdbook-alerts-icon"></span>
  tip
</p>
<p>Be sure to use the appropriate value for <em>status</em>.
Permanent redirection should use <a href="../../api/http.html#NNG_HTTP_STATUS_MOVED_PERMANENTLY"><code>NNG_HTTP_STATUS_MOVED_PERMANENTLY</code></a> (301)
and temporary redirections should use <a href="../../api/http.html#NNG_HTTP_STATUS_TEMPORARY_REDIRECT"><code>NNG_HTTP_STATUS_TEMPORARY_REDIRECT</code></a> (307).
In REST APIs, using a redirection to supply the new location of an object
created with <code>POST</code> should use <a href="../../api/http.html#NNG_HTTP_STATUS_SEE_OTHER"><code>NNG_HTTP_STATUS_SEE_OTHER</code></a> (303).</p>
</div>
<h3 id="collecting-request-body"><a class="header" href="#collecting-request-body">Collecting Request Body</a></h3>
<pre><code class="language-c">void nng_http_handler_collect_body(nng_http_handler *handler, bool want, size_t maxsz);
</code></pre>
<p>The <a name="a046"></a><code>nng_http_handler_collect_body</code> function requests that HTTP server
framework collect any request body for the request and attach it to the
connection before calling the callback for the <em>handler</em>.</p>
<p>Subsequently the data can be retrieved by the handler from the request with the
<a href="../../api/http.html#retrieving-body-content"><code>nng_http_get_body</code></a> function.</p>
<p>The collection is enabled if <em>want</em> is true.
Furthermore, the data that the client may sent is limited by the
value of <em>maxsz</em>.
If the client attempts to send more data than <em>maxsz</em>, then the
request will be terminated with <a href="../../api/http.html#NNG_HTTP_STATUS_CONTENT_TOO_LARGE"><code>NNG_HTTP_STATUS_CONTENT_TOO_LARGE</code></a> (413).</p>
<div class="mdbook-alerts mdbook-alerts-tip">
<p class="mdbook-alerts-title">
  <span class="mdbook-alerts-icon"></span>
  tip
</p>
<p>Limiting the size of incoming request data can provide protection
against denial of service attacks, as a buffer of the client-supplied
size must be allocated to receive the data.</p>
</div>
<blockquote>
<p>In order to provide an unlimited size, use <code>(size_t)-1</code> for <em>maxsz</em>.
The value <code>0</code> for <em>maxsz</em> can be used to prevent any data from being passed
by the client.</p>
</blockquote>
<blockquote>
<p>The built-in handlers for files, directories, and static data limit the
<em>maxsz</em> to zero by default.
Otherwise the default setting is to enable this capability with a default
value of <em>maxsz</em> of 1 megabyte.</p>
</blockquote>
<div class="mdbook-alerts mdbook-alerts-note">
<p class="mdbook-alerts-title">
  <span class="mdbook-alerts-icon"></span>
  note
</p>
<p>NNG specifically does not support the <code>Chunked</code> transfer-encoding.
This is considered a bug, and is a deficiency for full HTTP/1.1 compliance.
However, few clients send data in this format, so in practice this should
create few limitations.</p>
</div>
<h3 id="setting-callback-argument"><a class="header" href="#setting-callback-argument">Setting Callback Argument</a></h3>
<pre><code class="language-c">void nng_http_handler_set_data(nng_http_handler *handler, void *data,
    void (*dtor)(void *));
</code></pre>
<p>The <a name="a047"></a><code>nng_http_handler_set_data</code> function is used to set the
<em>data</em> argument that will be passed to the callback.</p>
<p>Additionally, when the handler is deallocated, if <em>dtor</em> is not <code>NULL</code>,
then it will be called with <em>data</em> as its argument.
The intended use of this function is deallocate any resources associated with <em>data</em>.</p>
<h3 id="setting-the-method"><a class="header" href="#setting-the-method">Setting the Method</a></h3>
<pre><code class="language-c">void nng_http_handler_set_method(nng_http_handler *handler, const char *method);
</code></pre>
<p>The <a name="a048"></a><code>nng_http_handler_set_method</code> function sets the <em>method</em> that the
<em>handler</em> will be called for, such as “GET” or “POST”.
(By default the “GET” method is handled.)</p>
<p>If <em>method</em> is <code>NULL</code> the handler will be executed for all methods.
The handler may determine the actual method used with the <a href="../../api/http.html#http-method"><code>nng_http_get_method</code></a> function.</p>
<p>The server will automatically call “GET” handlers if the client
sends a “HEAD” request, and will suppress HTTP body data in the responses
sent for such requests.</p>
<div class="mdbook-alerts mdbook-alerts-note">
<p class="mdbook-alerts-title">
  <span class="mdbook-alerts-icon"></span>
  note
</p>
<p>If <em>method</em> is longer than 32-bytes, it may be truncated silently.</p>
</div>
<h3 id="filtering-by-host"><a class="header" href="#filtering-by-host">Filtering by Host</a></h3>
<pre><code class="language-c">void nng_http_handler_set_host(nng_http_handler *handler, const char *host);
</code></pre>
<p>The <a name="a049"></a><code>nng_http_handler_set_host</code> function is used to limit the scope of the
<em>handler</em> so that it will only be called when the specified <em>host</em> matches
the value of the <code>Host:</code> HTTP header.</p>
<p>This can be used to create servers with different content for different virtual hosts.</p>
<p>The value of the <em>host</em> can include a colon and port, and should match
exactly the value of the <code>Host</code> header sent by the client.
(Canonicalization of the host name is performed.)</p>
<div class="mdbook-alerts mdbook-alerts-note">
<p class="mdbook-alerts-title">
  <span class="mdbook-alerts-icon"></span>
  note
</p>
<p>The port number may be ignored; at present the HTTP server framework
does not support a single server listening on different ports concurrently.</p>
</div>
<h3 id="handling-an-entire-tree"><a class="header" href="#handling-an-entire-tree">Handling an Entire Tree</a></h3>
<pre><code class="language-c">void nng_http_handler_set_tree(nng_http_handler *handler);
</code></pre>
<p>The <a name="a050"></a><code>nng_http_handler_set_tree</code> function causes the <em>handler</em> to be matched if the request URI sent
by the client is a logical child of the path for <em>handler</em>, and no more specific
<em>handler</em> has been registered.</p>
<p>This is useful in cases when the handler would like to examine the entire path
and possibly behave differently; for example a REST API that uses the rest of
the path to pass additional parameters.</p>
<div class="mdbook-alerts mdbook-alerts-tip">
<p class="mdbook-alerts-title">
  <span class="mdbook-alerts-icon"></span>
  tip
</p>
<p>This function is useful when constructing API handlers where a single
service address (path) supports dynamically generated children.
It can also provide a logical fallback instead of relying on a 404 error code.</p>
</div>
<h3 id="sending-the-response-explicitly"><a class="header" href="#sending-the-response-explicitly">Sending the Response Explicitly</a></h3>
<pre><code class="language-c">void nng_http_write_response(nng_http *conn, nng_aio *aio);
</code></pre>
<p>Normally the server will send any attached response, but there are circumstances where
a response must be sent manually, such as when <a href="../../api/http.html#hijacking-connections">hijacking</a> a connection.</p>
<p>In such a case, <a name="a051"></a><code>nng_http_write_response</code> can be called, which will send the response and any attached data, asynchronously
using the <a href="../../api/aio.html#asynchronous-io-handle"><code>nng_aio</code></a> <em>aio</em>.</p>
<p>By default, for <code>HTTP/1.1</code> connections, the connection is kept open, and
will be reused to receive new requests. For <code>HTTP/1.0</code>, or if the client has requested
explicitly by setting the “Connection: close” header, the connection will be closed after the
response is fully sent.</p>
<!-- NOTE: This assumes that any page referencing this is located
     in a directory two levels down.  Meaning ./api/somefile.md or
     similar.  mdbook cannot accommodate links that are called from
     different levels in the hierarchy. -->
<!-- Symbol cross reference -->
<!-- HTTP -->
<!-- HTTP Status -->
<!-- TLS -->
<!-- Macros -->
<!-- Protocols -->
<!-- Transports -->
<!-- Concept index -->

                    </main>

                    <nav class="nav-wrapper" aria-label="Page navigation">
                        <!-- Mobile navigation buttons -->
                            <a rel="prev" href="../api/stream.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
                                <i class="fa fa-angle-left"></i>
                            </a>

                            <a rel="next prefetch" href="../api/misc.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
                                <i class="fa fa-angle-right"></i>
                            </a>

                        <div style="clear: both"></div>
                    </nav>
                </div>
            </div>

            <nav class="nav-wide-wrapper" aria-label="Page navigation">
                    <a rel="prev" href="../api/stream.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
                        <i class="fa fa-angle-left"></i>
                    </a>

                    <a rel="next prefetch" href="../api/misc.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
                        <i class="fa fa-angle-right"></i>
                    </a>
            </nav>

        </div>




        <script>
            window.playground_copyable = true;
        </script>


        <script src="../elasticlunr.min.js"></script>
        <script src="../mark.min.js"></script>
        <script src="../searcher.js"></script>

        <script src="../clipboard.min.js"></script>
        <script src="../highlight.js"></script>
        <script src="../book.js"></script>

        <!-- Custom JS scripts -->
        <script src="../theme/pagetoc.js"></script>



    </div>
    </body>
</html>