From dd87dbaec43ffc5312b78b10316023dc7b78a06d Mon Sep 17 00:00:00 2001 From: Connor Prussin Date: Sat, 22 Jul 2017 20:19:56 -0700 Subject: [PATCH 1/7] Add https server support --- bower.json | 3 +- src/Node/HTTP.js | 11 +++ src/Node/HTTP.purs | 222 +++++++++++++++++++++++++++++++++++++++++++++ test/Main.purs | 138 ++++++++++++++++++++++------ 4 files changed, 345 insertions(+), 29 deletions(-) diff --git a/bower.json b/bower.json index 53ae436..87d721b 100644 --- a/bower.json +++ b/bower.json @@ -19,6 +19,7 @@ "purescript-node-streams": "^3.0.0", "purescript-node-url": "^3.0.0", "purescript-options": "^3.0.0", - "purescript-unsafe-coerce": "^3.0.0" + "purescript-unsafe-coerce": "^3.0.0", + "purescript-node-buffer": "^3.0.1" } } diff --git a/src/Node/HTTP.js b/src/Node/HTTP.js index 8e294fc..1cdae44 100644 --- a/src/Node/HTTP.js +++ b/src/Node/HTTP.js @@ -1,6 +1,17 @@ "use strict"; var http = require("http"); +var https = require("https"); + +exports.createServerSImpl = function (options) { + return function (handleRequest) { + return function () { + return https.createServer(options, function (req, res) { + handleRequest(req)(res)(); + }); + }; + }; +}; exports.createServer = function (handleRequest) { return function () { diff --git a/src/Node/HTTP.purs b/src/Node/HTTP.purs index 120fda6..298f21d 100644 --- a/src/Node/HTTP.purs +++ b/src/Node/HTTP.purs @@ -6,6 +6,29 @@ module Node.HTTP , Response , HTTP + , createServerS + , SSLOptions + , handshakeTimeout + , requestCert + , rejectUnauthorized + , npnProtocols + , alpnProtocols + , sessionTimeout + , ticketKeys + , pfx + , key + , passphrase + , cert + , ca + , crl + , ciphers + , honorCipherOrder + , ecdhCurve + , dhparam + , secureProtocol + , secureOptions + , sessionIdContext + , createServer , listen , ListenOptions @@ -28,10 +51,13 @@ import Prelude import Control.Monad.Eff (Eff, kind Effect) +import Data.Foreign (Foreign) import Data.Maybe (Maybe) import Data.Nullable (Nullable, toNullable) +import Data.Options (Options, Option, options, opt) import Data.StrMap (StrMap) +import Node.Buffer (Buffer) import Node.Stream (Writable, Readable) import Unsafe.Coerce (unsafeCoerce) @@ -51,6 +77,202 @@ foreign import data HTTP :: Effect -- | Create a HTTP server, given a function to be executed when a request is received. foreign import createServer :: forall eff. (Request -> Response -> Eff (http :: HTTP | eff) Unit) -> Eff (http :: HTTP | eff) Server +-- | The type of HTTPS server options +data SSLOptions + +-- | Abort the connection if the SSL/TLS handshake does not finish in the +-- | specified number of milliseconds. Defaults to 120 seconds. A +-- | 'tlsClientError' is emitted on the tls.Server object whenever a handshake +-- | times out. +-- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener) +handshakeTimeout :: Option SSLOptions Int +handshakeTimeout = opt "handshakeTimeout" + +-- | If true the server will request a certificate from clients that connect and +-- | attempt to verify that certificate. Defaults to false. +-- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener) +requestCert :: Option SSLOptions Boolean +requestCert = opt "requestCert" + +-- | If not false the server will reject any connection which is not authorized +-- | with the list of supplied CAs. This option only has an effect if +-- | requestCert is true. Defaults to true. +-- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener) +rejectUnauthorized :: Option SSLOptions Boolean +rejectUnauthorized = opt "rejectUnauthorized" + +-- | An array of strings, Buffers or Uint8Arrays, or a single Buffer or +-- | Uint8Array containing supported NPN protocols. Buffers should have the +-- | format [len][name][len][name]... e.g. 0x05hello0x05world, where the first +-- | byte is the length of the next protocol name. Passing an array is usually +-- | much simpler, e.g. ['hello', 'world']. (Protocols should be ordered by +-- | their priority.) +-- | The type variable t should be a string[], Buffer[], Uint8Array[], Buffer, +-- | or Uint8Array. +-- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener) +npnProtocols :: forall t. Option SSLOptions t +npnProtocols = opt "NPNProtocols" + +-- | An array of strings, Buffers or Uint8Arrays, or a single Buffer or +-- | Uint8Array containing the supported ALPN protocols. Buffers should have the +-- | format [len][name][len][name]... e.g. 0x05hello0x05world, where the first +-- | byte is the length of the next protocol name. Passing an array is usually +-- | much simpler, e.g. ['hello', 'world']. (Protocols should be ordered by +-- | their priority.) When the server receives both NPN and ALPN extensions from +-- | the client, ALPN takes precedence over NPN and the server does not send an +-- | NPN extension to the client. +-- | The type variable t should be a string[], Buffer[], Uint8Array[], Buffer, +-- | or Uint8Array. +-- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener) +alpnProtocols :: forall t. Option SSLOptions t +alpnProtocols = opt "ALPNProtocols" + +-- | An integer specifying the number of seconds after which the TLS session +-- | identifiers and TLS session tickets created by the server will time out. +-- | See SSL_CTX_set_timeout for more details. +-- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener) +sessionTimeout :: Option SSLOptions Int +sessionTimeout = opt "sessionTimeout" + +-- | A 48-byte Buffer instance consisting of a 16-byte prefix, a 16-byte HMAC +-- | key, and a 16-byte AES key. This can be used to accept TLS session tickets +-- | on multiple instances of the TLS server. +-- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener) +ticketKeys :: Option SSLOptions Buffer +ticketKeys = opt "ticketKeys" + +-- | Optional PFX or PKCS12 encoded private key and certificate chain. pfx is an +-- | alternative to providing key and cert individually. PFX is usually +-- | encrypted, if it is, passphrase will be used to decrypt it. +-- | The type variable t should be a string or Buffer. +-- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) +pfx :: forall t. Option SSLOptions t +pfx = opt "pfx" + +-- | Optional private keys in PEM format. PEM allows the option of private keys +-- | being encrypted. Encrypted keys will be decrypted with options.passphrase. +-- | Multiple keys using different algorithms can be provided either as an array +-- | of unencrypted key strings or buffers, or an array of objects in the form +-- | {pem: [, passphrase: ]}. The object form can only +-- | occur in an array. object.passphrase is optional. Encrypted keys will be +-- | decrypted with object.passphrase if provided, or options.passphrase if it +-- | is not. +-- | The type variable t should be a string, string[], Buffer, Buffer[], or +-- | Object[]. +-- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) +key :: forall t. Option SSLOptions t +key = opt "key" + +-- | Optional shared passphrase used for a single private key and/or a PFX. +-- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) +passphrase :: Option SSLOptions String +passphrase = opt "passphrase" + +-- | Optional cert chains in PEM format. One cert chain should be provided per +-- | private key. Each cert chain should consist of the PEM formatted +-- | certificate for a provided private key, followed by the PEM formatted +-- | intermediate certificates (if any), in order, and not including the root CA +-- | (the root CA must be pre-known to the peer, see ca). When providing +-- | multiple cert chains, they do not have to be in the same order as their +-- | private keys in key. If the intermediate certificates are not provided, the +-- | peer will not be able to validate the certificate, and the handshake will +-- | fail. +-- | The type variable t should be a string, string[], Buffer, or Buffer[]. +-- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) +cert :: forall t. Option SSLOptions t +cert = opt "cert" + +-- | Optionally override the trusted CA certificates. Default is to trust the +-- | well-known CAs curated by Mozilla. Mozilla's CAs are completely replaced +-- | when CAs are explicitly specified using this option. The value can be a +-- | string or Buffer, or an Array of strings and/or Buffers. Any string or +-- | Buffer can contain multiple PEM CAs concatenated together. The peer's +-- | certificate must be chainable to a CA trusted by the server for the +-- | connection to be authenticated. When using certificates that are not +-- | chainable to a well-known CA, the certificate's CA must be explicitly +-- | specified as a trusted or the connection will fail to authenticate. If the +-- | peer uses a certificate that doesn't match or chain to one of the default +-- | CAs, use the ca option to provide a CA certificate that the peer's +-- | certificate can match or chain to. For self-signed certificates, the +-- | certificate is its own CA, and must be provided. +-- | The type variable t should be a string, string[], Buffer, or Buffer[]. +-- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) +ca :: forall t. Option SSLOptions t +ca = opt "ca" + +-- | Optional PEM formatted CRLs (Certificate Revocation Lists). +-- | The type variable t should be a string, string[], Buffer, or Buffer[]. +-- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) +crl :: forall t. Option SSLOptions t +crl = opt "crl" + +-- | Optional cipher suite specification, replacing the default. For more +-- | information, see modifying the default cipher suite. +-- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) +ciphers :: Option SSLOptions String +ciphers = opt "ciphers" + +-- | Attempt to use the server's cipher suite preferences instead of the +-- | client's. When true, causes SSL_OP_CIPHER_SERVER_PREFERENCE to be set in +-- | secureOptions, see OpenSSL Options for more information. +-- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) +honorCipherOrder :: Option SSLOptions Boolean +honorCipherOrder = opt "honorCipherOrder" + +-- | A string describing a named curve to use for ECDH key agreement or false to +-- | disable ECDH. Defaults to tls.DEFAULT_ECDH_CURVE. Use crypto.getCurves() to +-- | obtain a list of available curve names. On recent releases, openssl ecparam +-- | -list_curves will also display the name and description of each available +-- | elliptic curve. +-- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) +ecdhCurve :: Option SSLOptions String +ecdhCurve = opt "ecdhCurve" + +-- | Diffie Hellman parameters, required for Perfect Forward Secrecy. Use +-- | openssl dhparam to create the parameters. The key length must be greater +-- | than or equal to 1024 bits, otherwise an error will be thrown. It is +-- | strongly recommended to use 2048 bits or larger for stronger security. If +-- | omitted or invalid, the parameters are silently discarded and DHE ciphers +-- | will not be available. +-- | The type variable t should be a string or Buffer. +-- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) +dhparam :: forall t. Option SSLOptions t +dhparam = opt "dhparam" + +-- | Optional SSL method to use, default is "SSLv23_method". The possible values +-- | are listed as SSL_METHODS, use the function names as strings. For example, +-- | "SSLv3_method" to force SSL version 3. +-- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) +secureProtocol :: Option SSLOptions String +secureProtocol = opt "secureProtocol" + +-- | Optionally affect the OpenSSL protocol behavior, which is not usually +-- | necessary. This should be used carefully if at all! Value is a numeric +-- | bitmask of the SSL_OP_* options from OpenSSL Options. +-- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) +secureOptions :: Option SSLOptions Int +secureOptions = opt "secureOptions" + +-- | Optional opaque identifier used by servers to ensure session state is not +-- | shared between applications. Unused by clients. +-- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) +sessionIdContext :: Option SSLOptions String +sessionIdContext = opt "sessionIdContext" + +foreign import createServerSImpl :: + forall eff. + Foreign -> + (Request -> Response -> Eff (http :: HTTP | eff) Unit) -> + Eff (http :: HTTP | eff) Server + +-- | Create an HTTPS server, given the SSL options and a function to be executed +-- | when a request is received. +createServerS :: forall eff. + Options SSLOptions -> + (Request -> Response -> Eff (http :: HTTP | eff) Unit) -> + Eff (http :: HTTP | eff) Server +createServerS = createServerSImpl <<< options + foreign import listenImpl :: forall eff. Server -> Int -> String -> Nullable Int -> Eff (http :: HTTP | eff) Unit -> Eff (http :: HTTP | eff) Unit -- | Listen on a port in order to start accepting HTTP requests. The specified callback will be run when setup is complete. diff --git a/test/Main.purs b/test/Main.purs index 979d776..3e18c0f 100644 --- a/test/Main.purs +++ b/test/Main.purs @@ -7,47 +7,118 @@ import Control.Monad.Eff.Console (CONSOLE, log, logShow) import Data.Foldable (foldMap) import Data.Maybe (Maybe(..)) +import Data.Options (Options, (:=)) import Node.Encoding (Encoding(..)) -import Node.HTTP (HTTP, listen, createServer, setHeader, requestMethod, requestURL, responseAsStream, requestAsStream, setStatusCode) +import Node.HTTP (HTTP, Request, Response, listen, createServer, createServerS, key, cert, setHeader, requestMethod, requestURL, responseAsStream, requestAsStream, setStatusCode) import Node.HTTP.Client as Client import Node.Stream (Writable, end, pipe, writeString) import Partial.Unsafe (unsafeCrashWith) +import Unsafe.Coerce (unsafeCoerce) foreign import stdout :: forall eff r. Writable r eff main :: forall eff. Eff (console :: CONSOLE, http :: HTTP | eff) Unit main = do testBasic + testHttpsServer testHttps testCookies +respond :: forall eff. Request -> Response -> Eff (console :: CONSOLE, http :: HTTP | eff) Unit +respond req res = do + setStatusCode res 200 + let inputStream = requestAsStream req + outputStream = responseAsStream res + log (requestMethod req <> " " <> requestURL req) + case requestMethod req of + "GET" -> do + let html = foldMap (_ <> "\n") + [ "
" + , " " + , " " + , "
" + ] + setHeader res "Content-Type" "text/html" + _ <- writeString outputStream UTF8 html (pure unit) + end outputStream (pure unit) + "POST" -> void $ pipe inputStream outputStream + _ -> unsafeCrashWith "Unexpected HTTP method" + testBasic :: forall eff. Eff (console :: CONSOLE, http :: HTTP | eff) Unit testBasic = do server <- createServer respond listen server { hostname: "localhost", port: 8080, backlog: Nothing } $ void do log "Listening on port 8080." simpleReq "http://localhost:8080" - where - respond req res = do - setStatusCode res 200 - let inputStream = requestAsStream req - outputStream = responseAsStream res - log (requestMethod req <> " " <> requestURL req) - case requestMethod req of - "GET" -> do - let html = foldMap (_ <> "\n") - [ "
" - , " " - , " " - , "
" - ] - setHeader res "Content-Type" "text/html" - _ <- writeString outputStream UTF8 html (pure unit) - end outputStream (pure unit) - "POST" -> void $ pipe inputStream outputStream - _ -> unsafeCrashWith "Unexpected HTTP method" + +mockCert :: String +mockCert = + """-----BEGIN CERTIFICATE----- +MIIDWDCCAkCgAwIBAgIJAKm4yWuzx7UpMA0GCSqGSIb3DQEBCwUAMEExCzAJBgNV +BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMR0wGwYDVQQKDBRwdXJlc2NyaXB0 +LW5vZGUtaHR0cDAeFw0xNzA3MjMwMTM4MThaFw0xNzA4MjIwMTM4MThaMEExCzAJ +BgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMR0wGwYDVQQKDBRwdXJlc2Ny +aXB0LW5vZGUtaHR0cDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMrI +7YGwOVZJGemgeGm8e6MTydSQozxlHYwshHDb83pB2LUhkguSRHoUe9CO+uDGemKP +BHMHFCS1Nuhgal3mnCPNbY/57mA8LDIpjJ/j9UD85Aw5c89yEd8MuLoM1T0q/APa +LOmKMgzvfpA0S1/6Hr5Ef/tGdE1gFluVirhgUqvbIBJzqTraQq89jwf+4YmzjCO7 +/6FIY0pn4xgcSGyd3i2r/DGbL42QlNmq2MarxxdFJo1llK6YIBhS/fAJCp6hsAnX ++m4hClvJ17Rt+46q4C7KCP6J1U5jFIMtDF7jw6uBr/macenF/ApAHUW0dAiBP9qG +fI2l64syxNSUS3of9p0CAwEAAaNTMFEwHQYDVR0OBBYEFPlsFrLCVM6zgXzKMkDN +lzkLLoCfMB8GA1UdIwQYMBaAFPlsFrLCVM6zgXzKMkDNlzkLLoCfMA8GA1UdEwEB +/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAKvNsmnuO65CUnU1U85UlXYSpyA2 +f1SVCwKsRB9omFCbtJv8nZOrFSfooxdNJ0LiS7t4cs6v1+441+Sg4aLA14qy4ezv +Fmjt/0qfS3GNjJRr9KU9ZdZ3oxu7qf2ILUneSJOuU/OjP42rZUV6ruyauZB79PvB +25ENUhpA9z90REYjHuZzUeI60/aRwqQgCCwu5XYeIIxkD+WBPh2lxCfASwQ6/1Iq +fEkZtgzKvcprF8csbb2RNu2AVF2jdxChtl/FCUlSSX13VCROf6dOYJPid9s/wKpE +nN+b2NNE8OJeuskvEckzDe/hbkVptUNi4q2G8tBoKjPPTjdiLjtxuNz7OT0= +-----END CERTIFICATE-----""" + +mockKey :: String +mockKey = + """-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDKyO2BsDlWSRnp +oHhpvHujE8nUkKM8ZR2MLIRw2/N6Qdi1IZILkkR6FHvQjvrgxnpijwRzBxQktTbo +YGpd5pwjzW2P+e5gPCwyKYyf4/VA/OQMOXPPchHfDLi6DNU9KvwD2izpijIM736Q +NEtf+h6+RH/7RnRNYBZblYq4YFKr2yASc6k62kKvPY8H/uGJs4wju/+hSGNKZ+MY +HEhsnd4tq/wxmy+NkJTZqtjGq8cXRSaNZZSumCAYUv3wCQqeobAJ1/puIQpbyde0 +bfuOquAuygj+idVOYxSDLQxe48Orga/5mnHpxfwKQB1FtHQIgT/ahnyNpeuLMsTU +lEt6H/adAgMBAAECggEBALSe/54SXx/SAPitbFOSBPYefBmPszXqQsVGKbl00IvG +9sVvX2xbHg83C4masS9g2kXLaYUjevevSXb12ghFjjH9mmcxkPe64QrVI2KPYzY9 +isqwqczOp8hqxmdBYvYWwV6VCIgEBcyrzamYSsL0QEntLamc+Z6pxYBR1LuhYEGd +Vq0A+YL/4CZi320+pt05u/635Daon33JqhvDa0QK5xvFYKEcB+IY5eqByOx7nJl8 +A55oVagBVjpi//rwoge5aCfbcdyHUmBFYkuCI6SJhvwDmfSHWDkyWWsZAJY5sosN +a824N7XX5ZiBYir+E4ldC6ZlFOnQK5f6Fr0MJeM8uikCgYEA+HAgYgKBpezCrJ0B +I/inIfynaW8k3SCSQhYvqPK591cBKXwghCG2vpUwqIVO/ROP070L9/EtNrFs5fPv +xHQA8P3Weeail6gl9UR5oKNU3bcbIFunUtWi1ua86g/aaofub/hBq2xR+HSnV91W +Ycwewyfc/0j94kDOAFgSGOz0BscCgYEA0PUQXtuu05YTmz2TDtknCcQOVm/UnEg6 +1FsKPzmoxWsAMtHXf3FbD3vHql1JfPTJPNcxEEL6fhA1l7ntailHltx8dt9bXmYJ +ANM0n8uSKde5MoFbMhmyYTcRxJW9EC2ivqLotd5iL1mbfvdF02cWmr/5KNxUO1Hk +7TkJturwo3sCgYBc/gNxDEUhKX05BU/O+hz9QMgdVAf1aWK1r/5I/AoWBhAeSiMV +slToA4oCGlwVqMPWWtXnCfSFm2YKsQNXgqBzlGA6otTLdZo3s1jfgyOaFhbmRshb +3jGkxRuDdUmpRJZAfSl/k/0exfN5lRTnaHM/U2WKfPTjQqSZRl4HzHIPMwKBgFVE +W0zKClou+Is1oifB9wsmJM+izLiFRPRYviK0raj5k9gpBu3rXMRBt2VOsek6nk+k +ZFIFcuA0Txo99aKHe74U9PkxBcDMlEnw5Z17XYaTj/ALFyKnl8HRzf9RNxg99xYh +tiJYv+ogf7JcxvKQM4osYkkJN5oJPgiLaOpqjo23AoGBAN3g5kvsYj3OKGh89pGk +osLeL+NNUBDvFsrvFzPMwPGDup6AB1qX1pc4RfyQGzDJqUSTpioWI5v1O6Pmoiak +FO0u08Tb/091Bir5kgglUSi7VnFD3v8ffeKpkkJvtYUj7S9yoH9NQPVhKVCq6mna +TbGfXbnVfNmqgQh71+k02p6S +-----END PRIVATE KEY-----""" + +testHttpsServer :: forall eff. Eff (console :: CONSOLE, http :: HTTP | eff) Unit +testHttpsServer = do + server <- createServerS (key := mockKey <> cert := mockCert) respond + listen server { hostname: "localhost", port: 8081, backlog: Nothing } $ void do + log "Listening on port 8081." + complexReq $ + Client.protocol := "https:" <> + Client.method := "GET" <> + Client.hostname := "localhost" <> + Client.port := 8081 <> + Client.path := "/" <> + Client.rejectUnauthorized := false testHttps :: forall eff. Eff (console :: CONSOLE, http :: HTTP | eff) Unit testHttps = @@ -61,12 +132,23 @@ testCookies = simpleReq :: forall eff. String -> Eff (console :: CONSOLE, http :: HTTP | eff) Unit simpleReq uri = do log ("GET " <> uri <> ":") - req <- Client.requestFromURI uri \response -> void do - log "Headers:" - logShow $ Client.responseHeaders response - log "Cookies:" - logShow $ Client.responseCookies response - log "Response:" - let responseStream = Client.responseAsStream response - pipe responseStream stdout + req <- Client.requestFromURI uri logResponse end (Client.requestAsStream req) (pure unit) + +complexReq :: forall eff. Options Client.RequestOptions -> Eff (console :: CONSOLE, http :: HTTP | eff) Unit +complexReq options = do + log $ opts.method <> " " <> opts.hostname <> opts.path <> ":" + req <- Client.request options logResponse + end (Client.requestAsStream req) (pure unit) + where + opts = unsafeCoerce options + +logResponse :: forall eff. Client.Response -> Eff (console :: CONSOLE, http :: HTTP | eff) Unit +logResponse response = void do + log "Headers:" + logShow $ Client.responseHeaders response + log "Cookies:" + logShow $ Client.responseCookies response + log "Response:" + let responseStream = Client.responseAsStream response + pipe responseStream stdout From 5e01f061d6ccccc3f3c9e72549c94e736f4f22f5 Mon Sep 17 00:00:00 2001 From: Connor Prussin Date: Sun, 23 Jul 2017 20:14:20 -0700 Subject: [PATCH 2/7] Remove copied node docs --- src/Node/HTTP.purs | 88 ---------------------------------------------- 1 file changed, 88 deletions(-) diff --git a/src/Node/HTTP.purs b/src/Node/HTTP.purs index 298f21d..31c12b4 100644 --- a/src/Node/HTTP.purs +++ b/src/Node/HTTP.purs @@ -80,181 +80,93 @@ foreign import createServer :: forall eff. (Request -> Response -> Eff (http :: -- | The type of HTTPS server options data SSLOptions --- | Abort the connection if the SSL/TLS handshake does not finish in the --- | specified number of milliseconds. Defaults to 120 seconds. A --- | 'tlsClientError' is emitted on the tls.Server object whenever a handshake --- | times out. -- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener) handshakeTimeout :: Option SSLOptions Int handshakeTimeout = opt "handshakeTimeout" --- | If true the server will request a certificate from clients that connect and --- | attempt to verify that certificate. Defaults to false. -- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener) requestCert :: Option SSLOptions Boolean requestCert = opt "requestCert" --- | If not false the server will reject any connection which is not authorized --- | with the list of supplied CAs. This option only has an effect if --- | requestCert is true. Defaults to true. -- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener) rejectUnauthorized :: Option SSLOptions Boolean rejectUnauthorized = opt "rejectUnauthorized" --- | An array of strings, Buffers or Uint8Arrays, or a single Buffer or --- | Uint8Array containing supported NPN protocols. Buffers should have the --- | format [len][name][len][name]... e.g. 0x05hello0x05world, where the first --- | byte is the length of the next protocol name. Passing an array is usually --- | much simpler, e.g. ['hello', 'world']. (Protocols should be ordered by --- | their priority.) -- | The type variable t should be a string[], Buffer[], Uint8Array[], Buffer, -- | or Uint8Array. -- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener) npnProtocols :: forall t. Option SSLOptions t npnProtocols = opt "NPNProtocols" --- | An array of strings, Buffers or Uint8Arrays, or a single Buffer or --- | Uint8Array containing the supported ALPN protocols. Buffers should have the --- | format [len][name][len][name]... e.g. 0x05hello0x05world, where the first --- | byte is the length of the next protocol name. Passing an array is usually --- | much simpler, e.g. ['hello', 'world']. (Protocols should be ordered by --- | their priority.) When the server receives both NPN and ALPN extensions from --- | the client, ALPN takes precedence over NPN and the server does not send an --- | NPN extension to the client. -- | The type variable t should be a string[], Buffer[], Uint8Array[], Buffer, -- | or Uint8Array. -- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener) alpnProtocols :: forall t. Option SSLOptions t alpnProtocols = opt "ALPNProtocols" --- | An integer specifying the number of seconds after which the TLS session --- | identifiers and TLS session tickets created by the server will time out. --- | See SSL_CTX_set_timeout for more details. -- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener) sessionTimeout :: Option SSLOptions Int sessionTimeout = opt "sessionTimeout" --- | A 48-byte Buffer instance consisting of a 16-byte prefix, a 16-byte HMAC --- | key, and a 16-byte AES key. This can be used to accept TLS session tickets --- | on multiple instances of the TLS server. -- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener) ticketKeys :: Option SSLOptions Buffer ticketKeys = opt "ticketKeys" --- | Optional PFX or PKCS12 encoded private key and certificate chain. pfx is an --- | alternative to providing key and cert individually. PFX is usually --- | encrypted, if it is, passphrase will be used to decrypt it. -- | The type variable t should be a string or Buffer. -- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) pfx :: forall t. Option SSLOptions t pfx = opt "pfx" --- | Optional private keys in PEM format. PEM allows the option of private keys --- | being encrypted. Encrypted keys will be decrypted with options.passphrase. --- | Multiple keys using different algorithms can be provided either as an array --- | of unencrypted key strings or buffers, or an array of objects in the form --- | {pem: [, passphrase: ]}. The object form can only --- | occur in an array. object.passphrase is optional. Encrypted keys will be --- | decrypted with object.passphrase if provided, or options.passphrase if it --- | is not. -- | The type variable t should be a string, string[], Buffer, Buffer[], or -- | Object[]. -- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) key :: forall t. Option SSLOptions t key = opt "key" --- | Optional shared passphrase used for a single private key and/or a PFX. -- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) passphrase :: Option SSLOptions String passphrase = opt "passphrase" --- | Optional cert chains in PEM format. One cert chain should be provided per --- | private key. Each cert chain should consist of the PEM formatted --- | certificate for a provided private key, followed by the PEM formatted --- | intermediate certificates (if any), in order, and not including the root CA --- | (the root CA must be pre-known to the peer, see ca). When providing --- | multiple cert chains, they do not have to be in the same order as their --- | private keys in key. If the intermediate certificates are not provided, the --- | peer will not be able to validate the certificate, and the handshake will --- | fail. -- | The type variable t should be a string, string[], Buffer, or Buffer[]. -- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) cert :: forall t. Option SSLOptions t cert = opt "cert" --- | Optionally override the trusted CA certificates. Default is to trust the --- | well-known CAs curated by Mozilla. Mozilla's CAs are completely replaced --- | when CAs are explicitly specified using this option. The value can be a --- | string or Buffer, or an Array of strings and/or Buffers. Any string or --- | Buffer can contain multiple PEM CAs concatenated together. The peer's --- | certificate must be chainable to a CA trusted by the server for the --- | connection to be authenticated. When using certificates that are not --- | chainable to a well-known CA, the certificate's CA must be explicitly --- | specified as a trusted or the connection will fail to authenticate. If the --- | peer uses a certificate that doesn't match or chain to one of the default --- | CAs, use the ca option to provide a CA certificate that the peer's --- | certificate can match or chain to. For self-signed certificates, the --- | certificate is its own CA, and must be provided. -- | The type variable t should be a string, string[], Buffer, or Buffer[]. -- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) ca :: forall t. Option SSLOptions t ca = opt "ca" --- | Optional PEM formatted CRLs (Certificate Revocation Lists). -- | The type variable t should be a string, string[], Buffer, or Buffer[]. -- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) crl :: forall t. Option SSLOptions t crl = opt "crl" --- | Optional cipher suite specification, replacing the default. For more --- | information, see modifying the default cipher suite. -- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) ciphers :: Option SSLOptions String ciphers = opt "ciphers" --- | Attempt to use the server's cipher suite preferences instead of the --- | client's. When true, causes SSL_OP_CIPHER_SERVER_PREFERENCE to be set in --- | secureOptions, see OpenSSL Options for more information. -- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) honorCipherOrder :: Option SSLOptions Boolean honorCipherOrder = opt "honorCipherOrder" --- | A string describing a named curve to use for ECDH key agreement or false to --- | disable ECDH. Defaults to tls.DEFAULT_ECDH_CURVE. Use crypto.getCurves() to --- | obtain a list of available curve names. On recent releases, openssl ecparam --- | -list_curves will also display the name and description of each available --- | elliptic curve. -- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) ecdhCurve :: Option SSLOptions String ecdhCurve = opt "ecdhCurve" --- | Diffie Hellman parameters, required for Perfect Forward Secrecy. Use --- | openssl dhparam to create the parameters. The key length must be greater --- | than or equal to 1024 bits, otherwise an error will be thrown. It is --- | strongly recommended to use 2048 bits or larger for stronger security. If --- | omitted or invalid, the parameters are silently discarded and DHE ciphers --- | will not be available. -- | The type variable t should be a string or Buffer. -- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) dhparam :: forall t. Option SSLOptions t dhparam = opt "dhparam" --- | Optional SSL method to use, default is "SSLv23_method". The possible values --- | are listed as SSL_METHODS, use the function names as strings. For example, --- | "SSLv3_method" to force SSL version 3. -- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) secureProtocol :: Option SSLOptions String secureProtocol = opt "secureProtocol" --- | Optionally affect the OpenSSL protocol behavior, which is not usually --- | necessary. This should be used carefully if at all! Value is a numeric --- | bitmask of the SSL_OP_* options from OpenSSL Options. -- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) secureOptions :: Option SSLOptions Int secureOptions = opt "secureOptions" --- | Optional opaque identifier used by servers to ensure session state is not --- | shared between applications. Unused by clients. -- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) sessionIdContext :: Option SSLOptions String sessionIdContext = opt "sessionIdContext" From 60f9c5e6ba02b723264a2bcb41179146aaeb65cf Mon Sep 17 00:00:00 2001 From: Connor Prussin Date: Mon, 24 Jul 2017 09:29:40 -0700 Subject: [PATCH 3/7] Move SSL stuff to Node.HTTP.HTTPS --- src/Node/HTTP.js | 11 --- src/Node/HTTP.purs | 134 ------------------------------------ src/Node/HTTP/HTTPS.js | 13 ++++ src/Node/HTTP/HTTPS.purs | 143 +++++++++++++++++++++++++++++++++++++++ test/Main.purs | 5 +- 5 files changed, 159 insertions(+), 147 deletions(-) create mode 100644 src/Node/HTTP/HTTPS.js create mode 100644 src/Node/HTTP/HTTPS.purs diff --git a/src/Node/HTTP.js b/src/Node/HTTP.js index 1cdae44..8e294fc 100644 --- a/src/Node/HTTP.js +++ b/src/Node/HTTP.js @@ -1,17 +1,6 @@ "use strict"; var http = require("http"); -var https = require("https"); - -exports.createServerSImpl = function (options) { - return function (handleRequest) { - return function () { - return https.createServer(options, function (req, res) { - handleRequest(req)(res)(); - }); - }; - }; -}; exports.createServer = function (handleRequest) { return function () { diff --git a/src/Node/HTTP.purs b/src/Node/HTTP.purs index 31c12b4..120fda6 100644 --- a/src/Node/HTTP.purs +++ b/src/Node/HTTP.purs @@ -6,29 +6,6 @@ module Node.HTTP , Response , HTTP - , createServerS - , SSLOptions - , handshakeTimeout - , requestCert - , rejectUnauthorized - , npnProtocols - , alpnProtocols - , sessionTimeout - , ticketKeys - , pfx - , key - , passphrase - , cert - , ca - , crl - , ciphers - , honorCipherOrder - , ecdhCurve - , dhparam - , secureProtocol - , secureOptions - , sessionIdContext - , createServer , listen , ListenOptions @@ -51,13 +28,10 @@ import Prelude import Control.Monad.Eff (Eff, kind Effect) -import Data.Foreign (Foreign) import Data.Maybe (Maybe) import Data.Nullable (Nullable, toNullable) -import Data.Options (Options, Option, options, opt) import Data.StrMap (StrMap) -import Node.Buffer (Buffer) import Node.Stream (Writable, Readable) import Unsafe.Coerce (unsafeCoerce) @@ -77,114 +51,6 @@ foreign import data HTTP :: Effect -- | Create a HTTP server, given a function to be executed when a request is received. foreign import createServer :: forall eff. (Request -> Response -> Eff (http :: HTTP | eff) Unit) -> Eff (http :: HTTP | eff) Server --- | The type of HTTPS server options -data SSLOptions - --- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener) -handshakeTimeout :: Option SSLOptions Int -handshakeTimeout = opt "handshakeTimeout" - --- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener) -requestCert :: Option SSLOptions Boolean -requestCert = opt "requestCert" - --- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener) -rejectUnauthorized :: Option SSLOptions Boolean -rejectUnauthorized = opt "rejectUnauthorized" - --- | The type variable t should be a string[], Buffer[], Uint8Array[], Buffer, --- | or Uint8Array. --- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener) -npnProtocols :: forall t. Option SSLOptions t -npnProtocols = opt "NPNProtocols" - --- | The type variable t should be a string[], Buffer[], Uint8Array[], Buffer, --- | or Uint8Array. --- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener) -alpnProtocols :: forall t. Option SSLOptions t -alpnProtocols = opt "ALPNProtocols" - --- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener) -sessionTimeout :: Option SSLOptions Int -sessionTimeout = opt "sessionTimeout" - --- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener) -ticketKeys :: Option SSLOptions Buffer -ticketKeys = opt "ticketKeys" - --- | The type variable t should be a string or Buffer. --- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) -pfx :: forall t. Option SSLOptions t -pfx = opt "pfx" - --- | The type variable t should be a string, string[], Buffer, Buffer[], or --- | Object[]. --- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) -key :: forall t. Option SSLOptions t -key = opt "key" - --- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) -passphrase :: Option SSLOptions String -passphrase = opt "passphrase" - --- | The type variable t should be a string, string[], Buffer, or Buffer[]. --- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) -cert :: forall t. Option SSLOptions t -cert = opt "cert" - --- | The type variable t should be a string, string[], Buffer, or Buffer[]. --- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) -ca :: forall t. Option SSLOptions t -ca = opt "ca" - --- | The type variable t should be a string, string[], Buffer, or Buffer[]. --- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) -crl :: forall t. Option SSLOptions t -crl = opt "crl" - --- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) -ciphers :: Option SSLOptions String -ciphers = opt "ciphers" - --- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) -honorCipherOrder :: Option SSLOptions Boolean -honorCipherOrder = opt "honorCipherOrder" - --- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) -ecdhCurve :: Option SSLOptions String -ecdhCurve = opt "ecdhCurve" - --- | The type variable t should be a string or Buffer. --- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) -dhparam :: forall t. Option SSLOptions t -dhparam = opt "dhparam" - --- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) -secureProtocol :: Option SSLOptions String -secureProtocol = opt "secureProtocol" - --- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) -secureOptions :: Option SSLOptions Int -secureOptions = opt "secureOptions" - --- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) -sessionIdContext :: Option SSLOptions String -sessionIdContext = opt "sessionIdContext" - -foreign import createServerSImpl :: - forall eff. - Foreign -> - (Request -> Response -> Eff (http :: HTTP | eff) Unit) -> - Eff (http :: HTTP | eff) Server - --- | Create an HTTPS server, given the SSL options and a function to be executed --- | when a request is received. -createServerS :: forall eff. - Options SSLOptions -> - (Request -> Response -> Eff (http :: HTTP | eff) Unit) -> - Eff (http :: HTTP | eff) Server -createServerS = createServerSImpl <<< options - foreign import listenImpl :: forall eff. Server -> Int -> String -> Nullable Int -> Eff (http :: HTTP | eff) Unit -> Eff (http :: HTTP | eff) Unit -- | Listen on a port in order to start accepting HTTP requests. The specified callback will be run when setup is complete. diff --git a/src/Node/HTTP/HTTPS.js b/src/Node/HTTP/HTTPS.js new file mode 100644 index 0000000..1547296 --- /dev/null +++ b/src/Node/HTTP/HTTPS.js @@ -0,0 +1,13 @@ +"use strict"; + +var https = require("https"); + +exports.createServerImpl = function (options) { + return function (handleRequest) { + return function () { + return https.createServer(options, function (req, res) { + handleRequest(req)(res)(); + }); + }; + }; +}; diff --git a/src/Node/HTTP/HTTPS.purs b/src/Node/HTTP/HTTPS.purs new file mode 100644 index 0000000..a3ac611 --- /dev/null +++ b/src/Node/HTTP/HTTPS.purs @@ -0,0 +1,143 @@ +-- | This module defines low-level bindings to the Node HTTPS module. + +module Node.HTTP.HTTPS + ( createServer + + , SSLOptions + , handshakeTimeout + , requestCert + , rejectUnauthorized + , npnProtocols + , alpnProtocols + , sessionTimeout + , ticketKeys + , pfx + , key + , passphrase + , cert + , ca + , crl + , ciphers + , honorCipherOrder + , ecdhCurve + , dhparam + , secureProtocol + , secureOptions + , sessionIdContext + ) where + +import Prelude + +import Control.Monad.Eff (Eff) +import Data.Options (Options, Option, options, opt) +import Data.Foreign (Foreign) +import Node.Buffer (Buffer) +import Node.HTTP (Request, Response, Server, HTTP) + +-- | The type of HTTPS server options +data SSLOptions + +-- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener) +handshakeTimeout :: Option SSLOptions Int +handshakeTimeout = opt "handshakeTimeout" + +-- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener) +requestCert :: Option SSLOptions Boolean +requestCert = opt "requestCert" + +-- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener) +rejectUnauthorized :: Option SSLOptions Boolean +rejectUnauthorized = opt "rejectUnauthorized" + +-- | The type variable t should be a string[], Buffer[], Uint8Array[], Buffer, +-- | or Uint8Array. +-- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener) +npnProtocols :: forall t. Option SSLOptions t +npnProtocols = opt "NPNProtocols" + +-- | The type variable t should be a string[], Buffer[], Uint8Array[], Buffer, +-- | or Uint8Array. +-- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener) +alpnProtocols :: forall t. Option SSLOptions t +alpnProtocols = opt "ALPNProtocols" + +-- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener) +sessionTimeout :: Option SSLOptions Int +sessionTimeout = opt "sessionTimeout" + +-- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener) +ticketKeys :: Option SSLOptions Buffer +ticketKeys = opt "ticketKeys" + +-- | The type variable t should be a string or Buffer. +-- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) +pfx :: forall t. Option SSLOptions t +pfx = opt "pfx" + +-- | The type variable t should be a string, string[], Buffer, Buffer[], or +-- | Object[]. +-- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) +key :: forall t. Option SSLOptions t +key = opt "key" + +-- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) +passphrase :: Option SSLOptions String +passphrase = opt "passphrase" + +-- | The type variable t should be a string, string[], Buffer, or Buffer[]. +-- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) +cert :: forall t. Option SSLOptions t +cert = opt "cert" + +-- | The type variable t should be a string, string[], Buffer, or Buffer[]. +-- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) +ca :: forall t. Option SSLOptions t +ca = opt "ca" + +-- | The type variable t should be a string, string[], Buffer, or Buffer[]. +-- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) +crl :: forall t. Option SSLOptions t +crl = opt "crl" + +-- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) +ciphers :: Option SSLOptions String +ciphers = opt "ciphers" + +-- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) +honorCipherOrder :: Option SSLOptions Boolean +honorCipherOrder = opt "honorCipherOrder" + +-- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) +ecdhCurve :: Option SSLOptions String +ecdhCurve = opt "ecdhCurve" + +-- | The type variable t should be a string or Buffer. +-- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) +dhparam :: forall t. Option SSLOptions t +dhparam = opt "dhparam" + +-- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) +secureProtocol :: Option SSLOptions String +secureProtocol = opt "secureProtocol" + +-- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) +secureOptions :: Option SSLOptions Int +secureOptions = opt "secureOptions" + +-- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) +sessionIdContext :: Option SSLOptions String +sessionIdContext = opt "sessionIdContext" + +foreign import createServerImpl :: + forall eff. + Foreign -> + (Request -> Response -> Eff (http :: HTTP | eff) Unit) -> + Eff (http :: HTTP | eff) Server + +-- | Create an HTTPS server, given the SSL options and a function to be executed +-- | when a request is received. +createServer :: forall eff. + Options SSLOptions -> + (Request -> Response -> Eff (http :: HTTP | eff) Unit) -> + Eff (http :: HTTP | eff) Server +createServer = createServerImpl <<< options diff --git a/test/Main.purs b/test/Main.purs index 3e18c0f..60944a2 100644 --- a/test/Main.purs +++ b/test/Main.purs @@ -10,8 +10,9 @@ import Data.Maybe (Maybe(..)) import Data.Options (Options, (:=)) import Node.Encoding (Encoding(..)) -import Node.HTTP (HTTP, Request, Response, listen, createServer, createServerS, key, cert, setHeader, requestMethod, requestURL, responseAsStream, requestAsStream, setStatusCode) +import Node.HTTP (HTTP, Request, Response, listen, createServer, setHeader, requestMethod, requestURL, responseAsStream, requestAsStream, setStatusCode) import Node.HTTP.Client as Client +import Node.HTTP.HTTPS as HTTPS import Node.Stream (Writable, end, pipe, writeString) import Partial.Unsafe (unsafeCrashWith) @@ -109,7 +110,7 @@ TbGfXbnVfNmqgQh71+k02p6S testHttpsServer :: forall eff. Eff (console :: CONSOLE, http :: HTTP | eff) Unit testHttpsServer = do - server <- createServerS (key := mockKey <> cert := mockCert) respond + server <- HTTPS.createServer (HTTPS.key := mockKey <> HTTPS.cert := mockCert) respond listen server { hostname: "localhost", port: 8081, backlog: Nothing } $ void do log "Listening on port 8081." complexReq $ From e6bfe5ac04a5a1844ce4f897cb7250ead1227a76 Mon Sep 17 00:00:00 2001 From: Connor Prussin Date: Tue, 25 Jul 2017 08:10:41 -0700 Subject: [PATCH 4/7] Fully type options --- bower.json | 3 +- src/Node/HTTP/HTTPS.purs | 155 ++++++++++++++++++++++++++++++++------- test/Main.purs | 6 +- 3 files changed, 134 insertions(+), 30 deletions(-) diff --git a/bower.json b/bower.json index 87d721b..408c2e7 100644 --- a/bower.json +++ b/bower.json @@ -20,6 +20,7 @@ "purescript-node-url": "^3.0.0", "purescript-options": "^3.0.0", "purescript-unsafe-coerce": "^3.0.0", - "purescript-node-buffer": "^3.0.1" + "purescript-node-buffer": "^3.0.1", + "purescript-arraybuffer-types": "^2.0.0" } } diff --git a/src/Node/HTTP/HTTPS.purs b/src/Node/HTTP/HTTPS.purs index a3ac611..a6243f5 100644 --- a/src/Node/HTTP/HTTPS.purs +++ b/src/Node/HTTP/HTTPS.purs @@ -7,19 +7,27 @@ module Node.HTTP.HTTPS , handshakeTimeout , requestCert , rejectUnauthorized + , NPNProtocols(..) , npnProtocols + , ALPNProtocols(..) , alpnProtocols , sessionTimeout , ticketKeys + , PFX(..) , pfx + , Key(..) , key , passphrase + , Cert(..) , cert + , CA(..) , ca + , CRL(..) , crl , ciphers , honorCipherOrder , ecdhCurve + , DHParam(..) , dhparam , secureProtocol , secureOptions @@ -29,8 +37,10 @@ module Node.HTTP.HTTPS import Prelude import Control.Monad.Eff (Eff) +import Data.ArrayBuffer.Types (Uint8Array) +import Data.Foreign (Foreign, toForeign) +import Data.Functor.Contravariant (cmap) import Data.Options (Options, Option, options, opt) -import Data.Foreign (Foreign) import Node.Buffer (Buffer) import Node.HTTP (Request, Response, Server, HTTP) @@ -49,17 +59,47 @@ requestCert = opt "requestCert" rejectUnauthorized :: Option SSLOptions Boolean rejectUnauthorized = opt "rejectUnauthorized" --- | The type variable t should be a string[], Buffer[], Uint8Array[], Buffer, --- | or Uint8Array. +-- | The npnProtocols option can be a String, a Buffer, a Uint8Array, or an +-- | array of any of those types. +data NPNProtocols + = NPNProtocolsString String + | NPNProtocolsBuffer Buffer + | NPNProtocolsUint8Array Uint8Array + | NPNProtocolsStringArray (Array String) + | NPNProtocolsBufferArray (Array Buffer) + | NPNProtocolsUint8ArrayArray (Array Uint8Array) + -- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener) -npnProtocols :: forall t. Option SSLOptions t -npnProtocols = opt "NPNProtocols" +npnProtocols :: Option SSLOptions NPNProtocols +npnProtocols = cmap extract $ opt "NPNProtocols" + where + extract (NPNProtocolsString s) = toForeign s + extract (NPNProtocolsBuffer b) = toForeign b + extract (NPNProtocolsUint8Array u) = toForeign u + extract (NPNProtocolsStringArray sa) = toForeign sa + extract (NPNProtocolsBufferArray ba) = toForeign ba + extract (NPNProtocolsUint8ArrayArray ua) = toForeign ua + +-- | The alpnProtocols option can be a String, a Buffer, a Uint8Array, or an +-- | array of any of those types. +data ALPNProtocols + = ALPNProtocolsString String + | ALPNProtocolsBuffer Buffer + | ALPNProtocolsUint8Array Uint8Array + | ALPNProtocolsStringArray (Array String) + | ALPNProtocolsBufferArray (Array Buffer) + | ALPNProtocolsUint8ArrayArray (Array Uint8Array) --- | The type variable t should be a string[], Buffer[], Uint8Array[], Buffer, --- | or Uint8Array. -- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener) -alpnProtocols :: forall t. Option SSLOptions t -alpnProtocols = opt "ALPNProtocols" +alpnProtocols :: Option SSLOptions ALPNProtocols +alpnProtocols = cmap extract $ opt "ALPNProtocols" + where + extract (ALPNProtocolsString s) = toForeign s + extract (ALPNProtocolsBuffer b) = toForeign b + extract (ALPNProtocolsUint8Array u) = toForeign u + extract (ALPNProtocolsStringArray sa) = toForeign sa + extract (ALPNProtocolsBufferArray ba) = toForeign ba + extract (ALPNProtocolsUint8ArrayArray ua) = toForeign ua -- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener) sessionTimeout :: Option SSLOptions Int @@ -69,35 +109,87 @@ sessionTimeout = opt "sessionTimeout" ticketKeys :: Option SSLOptions Buffer ticketKeys = opt "ticketKeys" --- | The type variable t should be a string or Buffer. +-- | The PFX option can take either a String or a Buffer +data PFX = PFXString String | PFXBuffer Buffer + -- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) -pfx :: forall t. Option SSLOptions t -pfx = opt "pfx" +pfx :: Option SSLOptions PFX +pfx = cmap extract $ opt "pfx" + where + extract (PFXString s) = toForeign s + extract (PFXBuffer b) = toForeign b + +-- | The key option can be a String, a Buffer, an array of strings, or an array +-- | of buffers. +data Key + = KeyString String + | KeyBuffer Buffer + | KeyStringArray (Array String) + | KeyBufferArray (Array Buffer) --- | The type variable t should be a string, string[], Buffer, Buffer[], or --- | Object[]. -- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) -key :: forall t. Option SSLOptions t -key = opt "key" +key :: Option SSLOptions Key +key = cmap extract $ opt "key" + where + extract (KeyString s) = toForeign s + extract (KeyBuffer b) = toForeign b + extract (KeyStringArray sa) = toForeign sa + extract (KeyBufferArray ba) = toForeign ba -- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) passphrase :: Option SSLOptions String passphrase = opt "passphrase" --- | The type variable t should be a string, string[], Buffer, or Buffer[]. +-- | The cert option can be a String, a Buffer, an array of strings, or an array +-- | of buffers. +data Cert + = CertString String + | CertBuffer Buffer + | CertStringArray (Array String) + | CertBufferArray (Array Buffer) + -- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) -cert :: forall t. Option SSLOptions t -cert = opt "cert" +cert :: Option SSLOptions Cert +cert = cmap extract $ opt "cert" + where + extract (CertString s) = toForeign s + extract (CertBuffer b) = toForeign b + extract (CertStringArray sa) = toForeign sa + extract (CertBufferArray ba) = toForeign ba + +-- | The CA option can be a String, a Buffer, an array of strings, or an array +-- | of buffers. +data CA + = CAString String + | CABuffer Buffer + | CAStringArray (Array String) + | CABufferArray (Array Buffer) --- | The type variable t should be a string, string[], Buffer, or Buffer[]. -- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) -ca :: forall t. Option SSLOptions t -ca = opt "ca" +ca :: Option SSLOptions CA +ca = cmap extract $ opt "ca" + where + extract (CAString s) = toForeign s + extract (CABuffer b) = toForeign b + extract (CAStringArray sa) = toForeign sa + extract (CABufferArray ba) = toForeign ba + +-- | The CRL option can be a String, a Buffer, an array of strings, or an array +-- | of buffers. +data CRL + = CRLString String + | CRLBuffer Buffer + | CRLStringArray (Array String) + | CRLBufferArray (Array Buffer) --- | The type variable t should be a string, string[], Buffer, or Buffer[]. -- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) -crl :: forall t. Option SSLOptions t -crl = opt "crl" +crl :: Option SSLOptions CRL +crl = cmap extract $ opt "crl" + where + extract (CRLString s) = toForeign s + extract (CRLBuffer b) = toForeign b + extract (CRLStringArray sa) = toForeign sa + extract (CRLBufferArray ba) = toForeign ba -- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) ciphers :: Option SSLOptions String @@ -111,10 +203,15 @@ honorCipherOrder = opt "honorCipherOrder" ecdhCurve :: Option SSLOptions String ecdhCurve = opt "ecdhCurve" --- | The type variable t should be a string or Buffer. +-- | The DHParam option can take either a String or a Buffer +data DHParam = DHParamString String | DHParamBuffer Buffer + -- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) -dhparam :: forall t. Option SSLOptions t -dhparam = opt "dhparam" +dhparam :: Option SSLOptions DHParam +dhparam = cmap extract $ opt "dhparam" + where + extract (DHParamString s) = toForeign s + extract (DHParamBuffer b) = toForeign b -- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) secureProtocol :: Option SSLOptions String @@ -128,6 +225,8 @@ secureOptions = opt "secureOptions" sessionIdContext :: Option SSLOptions String sessionIdContext = opt "sessionIdContext" +-- | Create an HTTPS server, given the SSL options and a function to be executed +-- | when a request is received. foreign import createServerImpl :: forall eff. Foreign -> diff --git a/test/Main.purs b/test/Main.purs index 60944a2..0ab5230 100644 --- a/test/Main.purs +++ b/test/Main.purs @@ -110,7 +110,7 @@ TbGfXbnVfNmqgQh71+k02p6S testHttpsServer :: forall eff. Eff (console :: CONSOLE, http :: HTTP | eff) Unit testHttpsServer = do - server <- HTTPS.createServer (HTTPS.key := mockKey <> HTTPS.cert := mockCert) respond + server <- HTTPS.createServer sslOpts respond listen server { hostname: "localhost", port: 8081, backlog: Nothing } $ void do log "Listening on port 8081." complexReq $ @@ -120,6 +120,10 @@ testHttpsServer = do Client.port := 8081 <> Client.path := "/" <> Client.rejectUnauthorized := false + where + sslOpts = + HTTPS.key := HTTPS.KeyString mockKey <> + HTTPS.cert := HTTPS.CertString mockCert testHttps :: forall eff. Eff (console :: CONSOLE, http :: HTTP | eff) Unit testHttps = From f83eebab45f024f3293df3a40c977daaa02a6193 Mon Sep 17 00:00:00 2001 From: Connor Prussin Date: Tue, 25 Jul 2017 08:32:44 -0700 Subject: [PATCH 5/7] Fix indentation --- src/Node/HTTP/HTTPS.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Node/HTTP/HTTPS.js b/src/Node/HTTP/HTTPS.js index 1547296..5912654 100644 --- a/src/Node/HTTP/HTTPS.js +++ b/src/Node/HTTP/HTTPS.js @@ -3,11 +3,11 @@ var https = require("https"); exports.createServerImpl = function (options) { - return function (handleRequest) { - return function () { - return https.createServer(options, function (req, res) { - handleRequest(req)(res)(); - }); - }; + return function (handleRequest) { + return function () { + return https.createServer(options, function (req, res) { + handleRequest(req)(res)(); + }); }; + }; }; From a44ab69e6ea84d0dc33d4bc7500a3767d0e3ceb3 Mon Sep 17 00:00:00 2001 From: Connor Prussin Date: Mon, 31 Jul 2017 12:19:45 -0700 Subject: [PATCH 6/7] Rename HTTPS to Secure --- src/Node/HTTP/{HTTPS.js => Secure.js} | 0 src/Node/HTTP/{HTTPS.purs => Secure.purs} | 2 +- test/Main.purs | 12 ++++++------ 3 files changed, 7 insertions(+), 7 deletions(-) rename src/Node/HTTP/{HTTPS.js => Secure.js} (100%) rename src/Node/HTTP/{HTTPS.purs => Secure.purs} (99%) diff --git a/src/Node/HTTP/HTTPS.js b/src/Node/HTTP/Secure.js similarity index 100% rename from src/Node/HTTP/HTTPS.js rename to src/Node/HTTP/Secure.js diff --git a/src/Node/HTTP/HTTPS.purs b/src/Node/HTTP/Secure.purs similarity index 99% rename from src/Node/HTTP/HTTPS.purs rename to src/Node/HTTP/Secure.purs index a6243f5..a0c4ea1 100644 --- a/src/Node/HTTP/HTTPS.purs +++ b/src/Node/HTTP/Secure.purs @@ -1,6 +1,6 @@ -- | This module defines low-level bindings to the Node HTTPS module. -module Node.HTTP.HTTPS +module Node.HTTP.Secure ( createServer , SSLOptions diff --git a/test/Main.purs b/test/Main.purs index 0ab5230..938860b 100644 --- a/test/Main.purs +++ b/test/Main.purs @@ -7,12 +7,12 @@ import Control.Monad.Eff.Console (CONSOLE, log, logShow) import Data.Foldable (foldMap) import Data.Maybe (Maybe(..)) -import Data.Options (Options, (:=)) +import Data.Options (Options, options, (:=)) import Node.Encoding (Encoding(..)) import Node.HTTP (HTTP, Request, Response, listen, createServer, setHeader, requestMethod, requestURL, responseAsStream, requestAsStream, setStatusCode) import Node.HTTP.Client as Client -import Node.HTTP.HTTPS as HTTPS +import Node.HTTP.Secure as HTTPS import Node.Stream (Writable, end, pipe, writeString) import Partial.Unsafe (unsafeCrashWith) @@ -141,12 +141,12 @@ simpleReq uri = do end (Client.requestAsStream req) (pure unit) complexReq :: forall eff. Options Client.RequestOptions -> Eff (console :: CONSOLE, http :: HTTP | eff) Unit -complexReq options = do - log $ opts.method <> " " <> opts.hostname <> opts.path <> ":" - req <- Client.request options logResponse +complexReq opts = do + log $ optsR.method <> " " <> optsR.protocol <> "//" <> optsR.hostname <> ":" <> optsR.port <> optsR.path <> ":" + req <- Client.request opts logResponse end (Client.requestAsStream req) (pure unit) where - opts = unsafeCoerce options + optsR = unsafeCoerce $ options opts logResponse :: forall eff. Client.Response -> Eff (console :: CONSOLE, http :: HTTP | eff) Unit logResponse response = void do From e9ce94fedd69738c6e60abb1fe381faf1b4a743f Mon Sep 17 00:00:00 2001 From: Connor Prussin Date: Tue, 1 Aug 2017 10:59:17 -0700 Subject: [PATCH 7/7] Use functions to map each possible argument type --- src/Node/HTTP/Secure.purs | 216 ++++++++++++++++++++++---------------- test/Main.purs | 4 +- 2 files changed, 130 insertions(+), 90 deletions(-) diff --git a/src/Node/HTTP/Secure.purs b/src/Node/HTTP/Secure.purs index a0c4ea1..66fe288 100644 --- a/src/Node/HTTP/Secure.purs +++ b/src/Node/HTTP/Secure.purs @@ -7,28 +7,72 @@ module Node.HTTP.Secure , handshakeTimeout , requestCert , rejectUnauthorized - , NPNProtocols(..) + + , NPNProtocols + , npnProtocolsString + , npnProtocolsBuffer + , npnProtocolsUint8Array + , npnProtocolsStringArray + , npnProtocolsBufferArray + , npnProtocolsUint8ArrayArray , npnProtocols - , ALPNProtocols(..) + + , ALPNProtocols + , alpnProtocolsString + , alpnProtocolsBuffer + , alpnProtocolsUint8Array + , alpnProtocolsStringArray + , alpnProtocolsBufferArray + , alpnProtocolsUint8ArrayArray , alpnProtocols + , sessionTimeout , ticketKeys - , PFX(..) + + , PFX + , pfxString + , pfxBuffer , pfx - , Key(..) + + , Key + , keyString + , keyBuffer + , keyStringArray + , keyBufferArray , key + , passphrase - , Cert(..) + + , Cert + , certString + , certBuffer + , certStringArray + , certBufferArray , cert - , CA(..) + + , CA + , caString + , caBuffer + , caStringArray + , caBufferArray , ca - , CRL(..) + + , CRL + , crlString + , crlBuffer + , crlStringArray + , crlBufferArray , crl + , ciphers , honorCipherOrder , ecdhCurve - , DHParam(..) + + , DHParam + , dhparamString + , dhparamBuffer , dhparam + , secureProtocol , secureOptions , sessionIdContext @@ -38,11 +82,11 @@ import Prelude import Control.Monad.Eff (Eff) import Data.ArrayBuffer.Types (Uint8Array) -import Data.Foreign (Foreign, toForeign) -import Data.Functor.Contravariant (cmap) +import Data.Foreign (Foreign) import Data.Options (Options, Option, options, opt) import Node.Buffer (Buffer) import Node.HTTP (Request, Response, Server, HTTP) +import Unsafe.Coerce (unsafeCoerce) -- | The type of HTTPS server options data SSLOptions @@ -62,44 +106,42 @@ rejectUnauthorized = opt "rejectUnauthorized" -- | The npnProtocols option can be a String, a Buffer, a Uint8Array, or an -- | array of any of those types. data NPNProtocols - = NPNProtocolsString String - | NPNProtocolsBuffer Buffer - | NPNProtocolsUint8Array Uint8Array - | NPNProtocolsStringArray (Array String) - | NPNProtocolsBufferArray (Array Buffer) - | NPNProtocolsUint8ArrayArray (Array Uint8Array) +npnProtocolsString :: String -> NPNProtocols +npnProtocolsString = unsafeCoerce +npnProtocolsBuffer :: Buffer -> NPNProtocols +npnProtocolsBuffer = unsafeCoerce +npnProtocolsUint8Array :: Uint8Array -> NPNProtocols +npnProtocolsUint8Array = unsafeCoerce +npnProtocolsStringArray :: Array String -> NPNProtocols +npnProtocolsStringArray = unsafeCoerce +npnProtocolsBufferArray :: Array Buffer -> NPNProtocols +npnProtocolsBufferArray = unsafeCoerce +npnProtocolsUint8ArrayArray :: Array Uint8Array -> NPNProtocols +npnProtocolsUint8ArrayArray = unsafeCoerce -- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener) npnProtocols :: Option SSLOptions NPNProtocols -npnProtocols = cmap extract $ opt "NPNProtocols" - where - extract (NPNProtocolsString s) = toForeign s - extract (NPNProtocolsBuffer b) = toForeign b - extract (NPNProtocolsUint8Array u) = toForeign u - extract (NPNProtocolsStringArray sa) = toForeign sa - extract (NPNProtocolsBufferArray ba) = toForeign ba - extract (NPNProtocolsUint8ArrayArray ua) = toForeign ua +npnProtocols = opt "NPNProtocols" -- | The alpnProtocols option can be a String, a Buffer, a Uint8Array, or an -- | array of any of those types. data ALPNProtocols - = ALPNProtocolsString String - | ALPNProtocolsBuffer Buffer - | ALPNProtocolsUint8Array Uint8Array - | ALPNProtocolsStringArray (Array String) - | ALPNProtocolsBufferArray (Array Buffer) - | ALPNProtocolsUint8ArrayArray (Array Uint8Array) +alpnProtocolsString :: String -> ALPNProtocols +alpnProtocolsString = unsafeCoerce +alpnProtocolsBuffer :: Buffer -> ALPNProtocols +alpnProtocolsBuffer = unsafeCoerce +alpnProtocolsUint8Array :: Uint8Array -> ALPNProtocols +alpnProtocolsUint8Array = unsafeCoerce +alpnProtocolsStringArray :: Array String -> ALPNProtocols +alpnProtocolsStringArray = unsafeCoerce +alpnProtocolsBufferArray :: Array Buffer -> ALPNProtocols +alpnProtocolsBufferArray = unsafeCoerce +alpnProtocolsUint8ArrayArray :: Array Uint8Array -> ALPNProtocols +alpnProtocolsUint8ArrayArray = unsafeCoerce -- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener) alpnProtocols :: Option SSLOptions ALPNProtocols -alpnProtocols = cmap extract $ opt "ALPNProtocols" - where - extract (ALPNProtocolsString s) = toForeign s - extract (ALPNProtocolsBuffer b) = toForeign b - extract (ALPNProtocolsUint8Array u) = toForeign u - extract (ALPNProtocolsStringArray sa) = toForeign sa - extract (ALPNProtocolsBufferArray ba) = toForeign ba - extract (ALPNProtocolsUint8ArrayArray ua) = toForeign ua +alpnProtocols = opt "ALPNProtocols" -- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener) sessionTimeout :: Option SSLOptions Int @@ -110,31 +152,31 @@ ticketKeys :: Option SSLOptions Buffer ticketKeys = opt "ticketKeys" -- | The PFX option can take either a String or a Buffer -data PFX = PFXString String | PFXBuffer Buffer +data PFX +pfxString :: String -> PFX +pfxString = unsafeCoerce +pfxBuffer :: Buffer -> PFX +pfxBuffer = unsafeCoerce -- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) pfx :: Option SSLOptions PFX -pfx = cmap extract $ opt "pfx" - where - extract (PFXString s) = toForeign s - extract (PFXBuffer b) = toForeign b +pfx = opt "pfx" -- | The key option can be a String, a Buffer, an array of strings, or an array -- | of buffers. data Key - = KeyString String - | KeyBuffer Buffer - | KeyStringArray (Array String) - | KeyBufferArray (Array Buffer) +keyString :: String -> Key +keyString = unsafeCoerce +keyBuffer :: Buffer -> Key +keyBuffer = unsafeCoerce +keyStringArray :: Array String -> Key +keyStringArray = unsafeCoerce +keyBufferArray :: Array Buffer -> Key +keyBufferArray = unsafeCoerce -- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) key :: Option SSLOptions Key -key = cmap extract $ opt "key" - where - extract (KeyString s) = toForeign s - extract (KeyBuffer b) = toForeign b - extract (KeyStringArray sa) = toForeign sa - extract (KeyBufferArray ba) = toForeign ba +key = opt "key" -- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) passphrase :: Option SSLOptions String @@ -143,53 +185,50 @@ passphrase = opt "passphrase" -- | The cert option can be a String, a Buffer, an array of strings, or an array -- | of buffers. data Cert - = CertString String - | CertBuffer Buffer - | CertStringArray (Array String) - | CertBufferArray (Array Buffer) +certString :: String -> Cert +certString = unsafeCoerce +certBuffer :: Buffer -> Cert +certBuffer = unsafeCoerce +certStringArray :: Array String -> Cert +certStringArray = unsafeCoerce +certBufferArray :: Array Buffer -> Cert +certBufferArray = unsafeCoerce -- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) cert :: Option SSLOptions Cert -cert = cmap extract $ opt "cert" - where - extract (CertString s) = toForeign s - extract (CertBuffer b) = toForeign b - extract (CertStringArray sa) = toForeign sa - extract (CertBufferArray ba) = toForeign ba +cert = opt "cert" -- | The CA option can be a String, a Buffer, an array of strings, or an array -- | of buffers. data CA - = CAString String - | CABuffer Buffer - | CAStringArray (Array String) - | CABufferArray (Array Buffer) +caString :: String -> CA +caString = unsafeCoerce +caBuffer :: Buffer -> CA +caBuffer = unsafeCoerce +caStringArray :: Array String -> CA +caStringArray = unsafeCoerce +caBufferArray :: Array Buffer -> CA +caBufferArray = unsafeCoerce -- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) ca :: Option SSLOptions CA -ca = cmap extract $ opt "ca" - where - extract (CAString s) = toForeign s - extract (CABuffer b) = toForeign b - extract (CAStringArray sa) = toForeign sa - extract (CABufferArray ba) = toForeign ba +ca = opt "ca" -- | The CRL option can be a String, a Buffer, an array of strings, or an array -- | of buffers. data CRL - = CRLString String - | CRLBuffer Buffer - | CRLStringArray (Array String) - | CRLBufferArray (Array Buffer) +crlString :: String -> CRL +crlString = unsafeCoerce +crlBuffer :: Buffer -> CRL +crlBuffer = unsafeCoerce +crlStringArray :: Array String -> CRL +crlStringArray = unsafeCoerce +crlBufferArray :: Array Buffer -> CRL +crlBufferArray = unsafeCoerce -- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) crl :: Option SSLOptions CRL -crl = cmap extract $ opt "crl" - where - extract (CRLString s) = toForeign s - extract (CRLBuffer b) = toForeign b - extract (CRLStringArray sa) = toForeign sa - extract (CRLBufferArray ba) = toForeign ba +crl = opt "crl" -- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) ciphers :: Option SSLOptions String @@ -204,14 +243,15 @@ ecdhCurve :: Option SSLOptions String ecdhCurve = opt "ecdhCurve" -- | The DHParam option can take either a String or a Buffer -data DHParam = DHParamString String | DHParamBuffer Buffer +data DHParam +dhparamString :: String -> DHParam +dhparamString = unsafeCoerce +dhparamBuffer :: Buffer -> DHParam +dhparamBuffer = unsafeCoerce -- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) dhparam :: Option SSLOptions DHParam -dhparam = cmap extract $ opt "dhparam" - where - extract (DHParamString s) = toForeign s - extract (DHParamBuffer b) = toForeign b +dhparam = opt "dhparam" -- | See the [node docs](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) secureProtocol :: Option SSLOptions String diff --git a/test/Main.purs b/test/Main.purs index 938860b..e78d5a7 100644 --- a/test/Main.purs +++ b/test/Main.purs @@ -122,8 +122,8 @@ testHttpsServer = do Client.rejectUnauthorized := false where sslOpts = - HTTPS.key := HTTPS.KeyString mockKey <> - HTTPS.cert := HTTPS.CertString mockCert + HTTPS.key := HTTPS.keyString mockKey <> + HTTPS.cert := HTTPS.certString mockCert testHttps :: forall eff. Eff (console :: CONSOLE, http :: HTTP | eff) Unit testHttps =