Skip to content

Commit 6792233

Browse files
Flesh out more of the headers API
1 parent 8c32a46 commit 6792233

File tree

8 files changed

+92
-14
lines changed

8 files changed

+92
-14
lines changed

src/Node/Http2/Headers.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { sensitiveHeaders } from "node:http2";
2+
3+
export const mkHeadersImpl = (insensitive, sensitive, sensitiveKeys) =>
4+
({
5+
...insensitive,
6+
...sensitive,
7+
[sensitiveHeaders]: sensitiveKeys,
8+
});

src/Node/Http2/Headers.purs

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
module Node.Http2.Headers where
2+
3+
import Prelude
4+
5+
import Data.FoldableWithIndex (foldlWithIndex)
6+
import Data.Function.Uncurried (Fn3, runFn3)
7+
import Data.Maybe (Maybe)
8+
import Foreign.Object (Object)
9+
import Foreign.Object as Object
10+
import Node.Http2.Types (Headers)
11+
import Prim.Row as Row
12+
import Unsafe.Coerce (unsafeCoerce)
13+
14+
-- | Makes an `Headers` value where all headers are insensitive.
15+
mkHeadersI :: forall insensitive. { | insensitive } -> Headers
16+
mkHeadersI = unsafeCoerce
17+
18+
-- | Makes an `Headers` value containing both insensitive headers (first argument)
19+
-- | and sensitive headers (second argument).
20+
-- | ```
21+
-- | mkHeaders { ":method": "GET" } { "sensitive-header": "secret" }
22+
-- | ```
23+
-- |
24+
-- | Note: the `Union` and `Nub` constraints simply prove that labels in one record
25+
-- | do not appear in the other one.
26+
mkHeaders
27+
:: forall insensitive sensitive all
28+
. Row.Union insensitive sensitive all
29+
=> Row.Nub all all
30+
=> { | insensitive }
31+
-> { | sensitive }
32+
-> Headers
33+
mkHeaders insensitive sensitive =
34+
runFn3 mkHeadersImpl insensitive sensitive (Object.keys $ unsafeCoerce sensitive)
35+
36+
foreign import mkHeadersImpl :: forall insensitive sensitive. Fn3 { | insensitive } { | sensitive } (Array String) (Headers)
37+
38+
-- | Note: this is unsafe because
39+
-- | - a server response's ":status" pseudo header's value will have type `Int`, not `String`
40+
-- | - a server response's "set-cookie" header's value will have type `Array String`, not `String`
41+
-- |
42+
-- | See https://nodejs.org/dist/latest-v18.x/docs/api/http2.html#headers-object
43+
unsafeToObject :: Headers -> Object String
44+
unsafeToObject = unsafeCoerce
45+
46+
status :: Headers -> Maybe Int
47+
status = unsafeCoerce <<< lookup ":status"
48+
49+
method :: Headers -> Maybe String
50+
method = lookup ":method"
51+
52+
scheme :: Headers -> Maybe String
53+
scheme = lookup ":scheme"
54+
55+
authority :: Headers -> Maybe String
56+
authority = lookup ":authority"
57+
58+
path :: Headers -> Maybe String
59+
path = lookup ":path"
60+
61+
lookup :: String -> Headers -> Maybe String
62+
lookup key headers = Object.lookup key $ unsafeCoerce headers
63+
64+
printHeaders :: Headers -> String
65+
printHeaders = printHeaders' "; "
66+
67+
printHeaders' :: String -> Headers -> String
68+
printHeaders' sep r = _.val $ foldlWithIndex printKeyValue { init: true, val: "" } $ (unsafeCoerce r :: Object String)
69+
where
70+
printKeyValue k acc v = do
71+
let kv = k <> "=" <> v
72+
{ init: false
73+
, val: if acc.init then kv else acc.val <> sep <> kv
74+
}

src/Node/Http2/SensitiveHeaders.js

Lines changed: 0 additions & 1 deletion
This file was deleted.

src/Node/Http2/SensitiveHeaders.purs

Lines changed: 0 additions & 5 deletions
This file was deleted.

src/Node/Http2/Server.purs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ sessionHandle = EventHandle "session" mkEffectFn1
7272
sessionErrorHandle :: EventHandle2 Http2SecureServer Error (Http2Session Server)
7373
sessionErrorHandle = EventHandle "sessionError" \cb -> mkEffectFn2 \a b -> cb a b
7474

75-
streamHandle :: EventHandle4 Http2SecureServer (Http2Stream Server) Headers BitwiseFlag (Array String)
75+
streamHandle :: EventHandle4 Http2SecureServer (Http2Stream Server) (Headers) BitwiseFlag (Array String)
7676
streamHandle = EventHandle "stream" \cb -> mkEffectFn4 \a b c d -> cb a b c d
7777

7878
timeoutHandle :: EventHandle0 TlsServer

src/Node/Http2/Session.purs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ import Node.Buffer.Immutable (ImmutableBuffer)
6363
import Node.EventEmitter (EventEmitter, EventHandle(..))
6464
import Node.EventEmitter.UtilTypes (EventHandle0, EventHandle1, EventHandle2, EventHandle3, EventHandle4)
6565
import Node.Http2.ErrorCode (ErrorCode)
66-
import Node.Http2.FrameType (FrameType)
6766
import Node.Http2.Flags (BitwiseFlag)
67+
import Node.Http2.FrameType (FrameType)
6868
import Node.Http2.Types (Headers, Http2Session, Http2Stream, Settings, StreamId)
6969
import Node.Net.Types (Socket, TCP)
7070
import Node.TLS.Types (Client, Server)

src/Node/Http2/Types.purs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,12 @@ type Settings =
5252
-- | `Http2SecureServer` extends `TLS.Server`, `Net.Server` and `EventEmitter`
5353
foreign import data Http2SecureServer :: Type
5454

55+
-- | Type is provided below, but the corresponding bindings for the Compatibility API
56+
-- | is not provided.
5557
foreign import data Http2ServerRequest :: Type
58+
59+
-- | Type is provided below, but the corresponding bindings for the Compatibility API
60+
-- | is not provided.
5661
foreign import data Http2ServerResponse :: Type
5762

5863
-- | `allowHTTP1` <boolean> Incoming client connections that do not support HTTP/2 will be downgraded to HTTP/1.x when set to true. See the 'unknownProtocol' event. See ALPN negotiation. Default: false.

test/Test/Main.purs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,18 @@ module Test.Main where
33
import Prelude
44

55
import Data.Array as Array
6-
import Data.FoldableWithIndex (forWithIndex_)
76
import Effect (Effect)
87
import Effect.Class.Console (log)
98
import Effect.Exception as Exception
109
import Effect.Ref as Ref
11-
import Foreign.Object (Object)
1210
import Node.Buffer as Buffer
1311
import Node.Buffer.Immutable (ImmutableBuffer)
1412
import Node.Encoding (Encoding(..))
1513
import Node.EventEmitter (on)
1614
import Node.FS.Sync as FS
1715
import Node.Http2.Client as Client
1816
import Node.Http2.ErrorCode as ErrorCode
17+
import Node.Http2.Headers (printHeaders')
1918
import Node.Http2.Server as Server
2019
import Node.Http2.Session as Session
2120
import Node.Http2.Stream (toDuplex)
@@ -59,8 +58,7 @@ main = do
5958
on Server.streamHandle server.http2 \stream headers flags rawHeaders -> do
6059
streamId <- H2Stream.id stream
6160
log $ "server - onStream for id: " <> show streamId
62-
forWithIndex_ (unsafeCoerce headers :: Object String) \k v ->
63-
log $ k <> ": " <> v
61+
log $ printHeaders' "\n" headers
6462
log $ "server - onStream - Flags: " <> show flags
6563
log $ "server - onStream - Raw Headers: " <> show rawHeaders
6664
let duplex = H2Stream.toDuplex stream
@@ -102,8 +100,7 @@ main = do
102100
Stream.end duplex
103101
on H2Stream.responseHandle stream \headers flags -> do
104102
log "client - onResponse"
105-
forWithIndex_ (unsafeCoerce headers :: Object String) \k v ->
106-
log $ k <> ": " <> v
103+
log $ printHeaders' "\n" headers
107104
log $ "Flags: " <> show flags
108105
chunksRef <- Ref.new []
109106
on Stream.dataHandle duplex \buf ->

0 commit comments

Comments
 (0)