Merge branch 'devel' of https://github.com/Araq/Nimrod into devel
This commit is contained in:
commit
cb976c9c9a
4 changed files with 64 additions and 46 deletions
|
|
@ -37,6 +37,7 @@ type
|
||||||
|
|
||||||
AsyncHttpServer* = ref object
|
AsyncHttpServer* = ref object
|
||||||
socket: PAsyncSocket
|
socket: PAsyncSocket
|
||||||
|
reuseAddr: bool
|
||||||
|
|
||||||
HttpCode* = enum
|
HttpCode* = enum
|
||||||
Http200 = "200 OK",
|
Http200 = "200 OK",
|
||||||
|
|
@ -64,9 +65,10 @@ proc `==`*(protocol: tuple[orig: string, major, minor: int],
|
||||||
of HttpVer10: 0
|
of HttpVer10: 0
|
||||||
result = protocol.major == major and protocol.minor == minor
|
result = protocol.major == major and protocol.minor == minor
|
||||||
|
|
||||||
proc newAsyncHttpServer*(): PAsyncHttpServer =
|
proc newAsyncHttpServer*(reuseAddr = true): PAsyncHttpServer =
|
||||||
## Creates a new ``AsyncHttpServer`` instance.
|
## Creates a new ``AsyncHttpServer`` instance.
|
||||||
new result
|
new result
|
||||||
|
result.reuseAddr = reuseAddr
|
||||||
|
|
||||||
proc addHeaders(msg: var string, headers: PStringTable) =
|
proc addHeaders(msg: var string, headers: PStringTable) =
|
||||||
for k, v in headers:
|
for k, v in headers:
|
||||||
|
|
@ -210,6 +212,8 @@ proc serve*(server: PAsyncHttpServer, port: Port,
|
||||||
##
|
##
|
||||||
## When a request is made by a client the specified callback will be called.
|
## When a request is made by a client the specified callback will be called.
|
||||||
server.socket = newAsyncSocket()
|
server.socket = newAsyncSocket()
|
||||||
|
if server.reuseAddr:
|
||||||
|
server.socket.setSockOpt(OptReuseAddr, true)
|
||||||
server.socket.bindAddr(port, address)
|
server.socket.bindAddr(port, address)
|
||||||
server.socket.listen()
|
server.socket.listen()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,8 @@ import rawsockets
|
||||||
import net
|
import net
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
export SOBool
|
||||||
|
|
||||||
when defined(ssl):
|
when defined(ssl):
|
||||||
import openssl
|
import openssl
|
||||||
|
|
||||||
|
|
@ -425,6 +427,17 @@ when defined(ssl):
|
||||||
socket.bioOut = bioNew(bio_s_mem())
|
socket.bioOut = bioNew(bio_s_mem())
|
||||||
sslSetBio(socket.sslHandle, socket.bioIn, socket.bioOut)
|
sslSetBio(socket.sslHandle, socket.bioIn, socket.bioOut)
|
||||||
|
|
||||||
|
proc getSockOpt*(socket: AsyncSocket, opt: SOBool, level = SOL_SOCKET): bool {.
|
||||||
|
tags: [ReadIOEffect].} =
|
||||||
|
## Retrieves option ``opt`` as a boolean value.
|
||||||
|
var res = getSockOptInt(socket.fd, cint(level), toCInt(opt))
|
||||||
|
result = res != 0
|
||||||
|
|
||||||
|
proc setSockOpt*(socket: AsyncSocket, opt: SOBool, value: bool,
|
||||||
|
level = SOL_SOCKET) {.tags: [WriteIOEffect].} =
|
||||||
|
## Sets option ``opt`` to a boolean value specified by ``value``.
|
||||||
|
var valuei = cint(if value: 1 else: 0)
|
||||||
|
setSockOptInt(socket.fd, cint(level), toCInt(opt), valuei)
|
||||||
|
|
||||||
when isMainModule:
|
when isMainModule:
|
||||||
type
|
type
|
||||||
|
|
|
||||||
|
|
@ -17,27 +17,27 @@
|
||||||
##
|
##
|
||||||
## Retrieving a website
|
## Retrieving a website
|
||||||
## ====================
|
## ====================
|
||||||
##
|
##
|
||||||
## This example uses HTTP GET to retrieve
|
## This example uses HTTP GET to retrieve
|
||||||
## ``http://google.com``
|
## ``http://google.com``
|
||||||
##
|
##
|
||||||
## .. code-block:: Nim
|
## .. code-block:: Nim
|
||||||
## echo(getContent("http://google.com"))
|
## echo(getContent("http://google.com"))
|
||||||
##
|
##
|
||||||
## Using HTTP POST
|
## Using HTTP POST
|
||||||
## ===============
|
## ===============
|
||||||
##
|
##
|
||||||
## This example demonstrates the usage of the W3 HTML Validator, it
|
## This example demonstrates the usage of the W3 HTML Validator, it
|
||||||
## uses ``multipart/form-data`` as the ``Content-Type`` to send the HTML to
|
## uses ``multipart/form-data`` as the ``Content-Type`` to send the HTML to
|
||||||
## the server.
|
## the server.
|
||||||
##
|
##
|
||||||
## .. code-block:: Nim
|
## .. code-block:: Nim
|
||||||
## var headers: string = "Content-Type: multipart/form-data; boundary=xyz\c\L"
|
## var headers: string = "Content-Type: multipart/form-data; boundary=xyz\c\L"
|
||||||
## var body: string = "--xyz\c\L"
|
## var body: string = "--xyz\c\L"
|
||||||
## # soap 1.2 output
|
## # soap 1.2 output
|
||||||
## body.add("Content-Disposition: form-data; name=\"output\"\c\L")
|
## body.add("Content-Disposition: form-data; name=\"output\"\c\L")
|
||||||
## body.add("\c\Lsoap12\c\L")
|
## body.add("\c\Lsoap12\c\L")
|
||||||
##
|
##
|
||||||
## # html
|
## # html
|
||||||
## body.add("--xyz\c\L")
|
## body.add("--xyz\c\L")
|
||||||
## body.add("Content-Disposition: form-data; name=\"uploaded_file\";" &
|
## body.add("Content-Disposition: form-data; name=\"uploaded_file\";" &
|
||||||
|
|
@ -45,7 +45,7 @@
|
||||||
## body.add("Content-Type: text/html\c\L")
|
## body.add("Content-Type: text/html\c\L")
|
||||||
## body.add("\c\L<html><head></head><body><p>test</p></body></html>\c\L")
|
## body.add("\c\L<html><head></head><body><p>test</p></body></html>\c\L")
|
||||||
## body.add("--xyz--")
|
## body.add("--xyz--")
|
||||||
##
|
##
|
||||||
## echo(postContent("http://validator.w3.org/check", headers, body))
|
## echo(postContent("http://validator.w3.org/check", headers, body))
|
||||||
##
|
##
|
||||||
## Asynchronous HTTP requests
|
## Asynchronous HTTP requests
|
||||||
|
|
@ -95,8 +95,8 @@ from net import nil
|
||||||
|
|
||||||
type
|
type
|
||||||
Response* = tuple[
|
Response* = tuple[
|
||||||
version: string,
|
version: string,
|
||||||
status: string,
|
status: string,
|
||||||
headers: StringTableRef,
|
headers: StringTableRef,
|
||||||
body: string]
|
body: string]
|
||||||
|
|
||||||
|
|
@ -108,7 +108,7 @@ type
|
||||||
## does not conform to the implemented
|
## does not conform to the implemented
|
||||||
## protocol
|
## protocol
|
||||||
|
|
||||||
HttpRequestError* = object of IOError ## Thrown in the ``getContent`` proc
|
HttpRequestError* = object of IOError ## Thrown in the ``getContent`` proc
|
||||||
## and ``postContent`` proc,
|
## and ``postContent`` proc,
|
||||||
## when the server returns an error
|
## when the server returns an error
|
||||||
|
|
||||||
|
|
@ -123,7 +123,7 @@ proc httpError(msg: string) =
|
||||||
new(e)
|
new(e)
|
||||||
e.msg = msg
|
e.msg = msg
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
proc fileError(msg: string) =
|
proc fileError(msg: string) =
|
||||||
var e: ref IOError
|
var e: ref IOError
|
||||||
new(e)
|
new(e)
|
||||||
|
|
@ -167,7 +167,7 @@ proc parseChunks(s: TSocket, timeout: int): string =
|
||||||
s.skip(2, timeout) # Skip \c\L
|
s.skip(2, timeout) # Skip \c\L
|
||||||
# Trailer headers will only be sent if the request specifies that we want
|
# Trailer headers will only be sent if the request specifies that we want
|
||||||
# them: http://tools.ietf.org/html/rfc2616#section-3.6.1
|
# them: http://tools.ietf.org/html/rfc2616#section-3.6.1
|
||||||
|
|
||||||
proc parseBody(s: TSocket, headers: PStringTable, timeout: int): string =
|
proc parseBody(s: TSocket, headers: PStringTable, timeout: int): string =
|
||||||
result = ""
|
result = ""
|
||||||
if headers["Transfer-Encoding"] == "chunked":
|
if headers["Transfer-Encoding"] == "chunked":
|
||||||
|
|
@ -191,7 +191,7 @@ proc parseBody(s: TSocket, headers: PStringTable, timeout: int): string =
|
||||||
" got: " & $received)
|
" got: " & $received)
|
||||||
else:
|
else:
|
||||||
# (http://tools.ietf.org/html/rfc2616#section-4.4) NR.4 TODO
|
# (http://tools.ietf.org/html/rfc2616#section-4.4) NR.4 TODO
|
||||||
|
|
||||||
# -REGION- Connection: Close
|
# -REGION- Connection: Close
|
||||||
# (http://tools.ietf.org/html/rfc2616#section-4.4) NR.5
|
# (http://tools.ietf.org/html/rfc2616#section-4.4) NR.5
|
||||||
if headers["Connection"] == "close":
|
if headers["Connection"] == "close":
|
||||||
|
|
@ -241,7 +241,7 @@ proc parseResponse(s: TSocket, getBody: bool, timeout: int): TResponse =
|
||||||
inc(linei, le)
|
inc(linei, le)
|
||||||
if line[linei] != ':': httpError("invalid headers")
|
if line[linei] != ':': httpError("invalid headers")
|
||||||
inc(linei) # Skip :
|
inc(linei) # Skip :
|
||||||
|
|
||||||
result.headers[name] = line[linei.. -1].strip()
|
result.headers[name] = line[linei.. -1].strip()
|
||||||
if not fullyRead:
|
if not fullyRead:
|
||||||
httpError("Connection was closed before full request has been made")
|
httpError("Connection was closed before full request has been made")
|
||||||
|
|
@ -256,17 +256,17 @@ type
|
||||||
## correspond to a GET request, but without the response
|
## correspond to a GET request, but without the response
|
||||||
## body.
|
## body.
|
||||||
httpGET, ## Retrieves the specified resource.
|
httpGET, ## Retrieves the specified resource.
|
||||||
httpPOST, ## Submits data to be processed to the identified
|
httpPOST, ## Submits data to be processed to the identified
|
||||||
## resource. The data is included in the body of the
|
## resource. The data is included in the body of the
|
||||||
## request.
|
## request.
|
||||||
httpPUT, ## Uploads a representation of the specified resource.
|
httpPUT, ## Uploads a representation of the specified resource.
|
||||||
httpDELETE, ## Deletes the specified resource.
|
httpDELETE, ## Deletes the specified resource.
|
||||||
httpTRACE, ## Echoes back the received request, so that a client
|
httpTRACE, ## Echoes back the received request, so that a client
|
||||||
## can see what intermediate servers are adding or
|
## can see what intermediate servers are adding or
|
||||||
## changing in the request.
|
## changing in the request.
|
||||||
httpOPTIONS, ## Returns the HTTP methods that the server supports
|
httpOPTIONS, ## Returns the HTTP methods that the server supports
|
||||||
## for specified address.
|
## for specified address.
|
||||||
httpCONNECT ## Converts the request connection to a transparent
|
httpCONNECT ## Converts the request connection to a transparent
|
||||||
## TCP/IP tunnel, usually used for proxies.
|
## TCP/IP tunnel, usually used for proxies.
|
||||||
|
|
||||||
{.deprecated: [THttpMethod: HttpMethod].}
|
{.deprecated: [THttpMethod: HttpMethod].}
|
||||||
|
|
@ -281,7 +281,7 @@ proc newProxy*(url: string, auth = ""): PProxy =
|
||||||
## Constructs a new ``TProxy`` object.
|
## Constructs a new ``TProxy`` object.
|
||||||
result = PProxy(url: parseUrl(url), auth: auth)
|
result = PProxy(url: parseUrl(url), auth: auth)
|
||||||
|
|
||||||
proc request*(url: string, httpMethod = httpGET, extraHeaders = "",
|
proc request*(url: string, httpMethod = httpGET, extraHeaders = "",
|
||||||
body = "",
|
body = "",
|
||||||
sslContext: PSSLContext = defaultSSLContext,
|
sslContext: PSSLContext = defaultSSLContext,
|
||||||
timeout = -1, userAgent = defUserAgent,
|
timeout = -1, userAgent = defUserAgent,
|
||||||
|
|
@ -298,7 +298,7 @@ proc request*(url: string, httpMethod = httpGET, extraHeaders = "",
|
||||||
headers.add(" " & url)
|
headers.add(" " & url)
|
||||||
|
|
||||||
headers.add(" HTTP/1.1\c\L")
|
headers.add(" HTTP/1.1\c\L")
|
||||||
|
|
||||||
add(headers, "Host: " & r.hostname & "\c\L")
|
add(headers, "Host: " & r.hostname & "\c\L")
|
||||||
if userAgent != "":
|
if userAgent != "":
|
||||||
add(headers, "User-Agent: " & userAgent & "\c\L")
|
add(headers, "User-Agent: " & userAgent & "\c\L")
|
||||||
|
|
@ -307,7 +307,7 @@ proc request*(url: string, httpMethod = httpGET, extraHeaders = "",
|
||||||
add(headers, "Proxy-Authorization: basic " & auth & "\c\L")
|
add(headers, "Proxy-Authorization: basic " & auth & "\c\L")
|
||||||
add(headers, extraHeaders)
|
add(headers, extraHeaders)
|
||||||
add(headers, "\c\L")
|
add(headers, "\c\L")
|
||||||
|
|
||||||
var s = socket()
|
var s = socket()
|
||||||
if s == invalidSocket: raiseOSError(osLastError())
|
if s == invalidSocket: raiseOSError(osLastError())
|
||||||
var port = sockets.TPort(80)
|
var port = sockets.TPort(80)
|
||||||
|
|
@ -320,7 +320,7 @@ proc request*(url: string, httpMethod = httpGET, extraHeaders = "",
|
||||||
"SSL support is not available. Cannot connect over SSL.")
|
"SSL support is not available. Cannot connect over SSL.")
|
||||||
if r.port != "":
|
if r.port != "":
|
||||||
port = sockets.TPort(r.port.parseInt)
|
port = sockets.TPort(r.port.parseInt)
|
||||||
|
|
||||||
if timeout == -1:
|
if timeout == -1:
|
||||||
s.connect(r.hostname, port)
|
s.connect(r.hostname, port)
|
||||||
else:
|
else:
|
||||||
|
|
@ -328,10 +328,10 @@ proc request*(url: string, httpMethod = httpGET, extraHeaders = "",
|
||||||
s.send(headers)
|
s.send(headers)
|
||||||
if body != "":
|
if body != "":
|
||||||
s.send(body)
|
s.send(body)
|
||||||
|
|
||||||
result = parseResponse(s, httpMethod != httpHEAD, timeout)
|
result = parseResponse(s, httpMethod != httpHEAD, timeout)
|
||||||
s.close()
|
s.close()
|
||||||
|
|
||||||
proc redirection(status: string): bool =
|
proc redirection(status: string): bool =
|
||||||
const redirectionNRs = ["301", "302", "303", "307"]
|
const redirectionNRs = ["301", "302", "303", "307"]
|
||||||
for i in items(redirectionNRs):
|
for i in items(redirectionNRs):
|
||||||
|
|
@ -346,7 +346,7 @@ proc getNewLocation(lastUrl: string, headers: PStringTable): string =
|
||||||
if r.hostname == "" and r.path != "":
|
if r.hostname == "" and r.path != "":
|
||||||
let origParsed = parseURL(lastUrl)
|
let origParsed = parseURL(lastUrl)
|
||||||
result = origParsed.hostname & "/" & r.path
|
result = origParsed.hostname & "/" & r.path
|
||||||
|
|
||||||
proc get*(url: string, extraHeaders = "", maxRedirects = 5,
|
proc get*(url: string, extraHeaders = "", maxRedirects = 5,
|
||||||
sslContext: PSSLContext = defaultSSLContext,
|
sslContext: PSSLContext = defaultSSLContext,
|
||||||
timeout = -1, userAgent = defUserAgent,
|
timeout = -1, userAgent = defUserAgent,
|
||||||
|
|
@ -365,7 +365,7 @@ proc get*(url: string, extraHeaders = "", maxRedirects = 5,
|
||||||
result = request(redirectTo, httpGET, extraHeaders, "", sslContext,
|
result = request(redirectTo, httpGET, extraHeaders, "", sslContext,
|
||||||
timeout, userAgent, proxy)
|
timeout, userAgent, proxy)
|
||||||
lastUrl = redirectTo
|
lastUrl = redirectTo
|
||||||
|
|
||||||
proc getContent*(url: string, extraHeaders = "", maxRedirects = 5,
|
proc getContent*(url: string, extraHeaders = "", maxRedirects = 5,
|
||||||
sslContext: PSSLContext = defaultSSLContext,
|
sslContext: PSSLContext = defaultSSLContext,
|
||||||
timeout = -1, userAgent = defUserAgent,
|
timeout = -1, userAgent = defUserAgent,
|
||||||
|
|
@ -381,7 +381,7 @@ proc getContent*(url: string, extraHeaders = "", maxRedirects = 5,
|
||||||
raise newException(EHTTPRequestErr, r.status)
|
raise newException(EHTTPRequestErr, r.status)
|
||||||
else:
|
else:
|
||||||
return r.body
|
return r.body
|
||||||
|
|
||||||
proc post*(url: string, extraHeaders = "", body = "",
|
proc post*(url: string, extraHeaders = "", body = "",
|
||||||
maxRedirects = 5,
|
maxRedirects = 5,
|
||||||
sslContext: PSSLContext = defaultSSLContext,
|
sslContext: PSSLContext = defaultSSLContext,
|
||||||
|
|
@ -404,7 +404,7 @@ proc post*(url: string, extraHeaders = "", body = "",
|
||||||
result = request(redirectTo, meth, xh, body, sslContext, timeout,
|
result = request(redirectTo, meth, xh, body, sslContext, timeout,
|
||||||
userAgent, proxy)
|
userAgent, proxy)
|
||||||
lastUrl = redirectTo
|
lastUrl = redirectTo
|
||||||
|
|
||||||
proc postContent*(url: string, extraHeaders = "", body = "",
|
proc postContent*(url: string, extraHeaders = "", body = "",
|
||||||
maxRedirects = 5,
|
maxRedirects = 5,
|
||||||
sslContext: PSSLContext = defaultSSLContext,
|
sslContext: PSSLContext = defaultSSLContext,
|
||||||
|
|
@ -421,7 +421,7 @@ proc postContent*(url: string, extraHeaders = "", body = "",
|
||||||
raise newException(EHTTPRequestErr, r.status)
|
raise newException(EHTTPRequestErr, r.status)
|
||||||
else:
|
else:
|
||||||
return r.body
|
return r.body
|
||||||
|
|
||||||
proc downloadFile*(url: string, outputFilename: string,
|
proc downloadFile*(url: string, outputFilename: string,
|
||||||
sslContext: PSSLContext = defaultSSLContext,
|
sslContext: PSSLContext = defaultSSLContext,
|
||||||
timeout = -1, userAgent = defUserAgent,
|
timeout = -1, userAgent = defUserAgent,
|
||||||
|
|
@ -456,7 +456,7 @@ type
|
||||||
socket: AsyncSocket
|
socket: AsyncSocket
|
||||||
connected: bool
|
connected: bool
|
||||||
currentURL: TURL ## Where we are currently connected.
|
currentURL: TURL ## Where we are currently connected.
|
||||||
headers: StringTableRef
|
headers*: StringTableRef
|
||||||
maxRedirects: int
|
maxRedirects: int
|
||||||
userAgent: string
|
userAgent: string
|
||||||
when defined(ssl):
|
when defined(ssl):
|
||||||
|
|
@ -528,7 +528,7 @@ proc parseChunks(client: PAsyncHttpClient): Future[string] {.async.} =
|
||||||
discard await recvFull(client.socket, 2) # Skip \c\L
|
discard await recvFull(client.socket, 2) # Skip \c\L
|
||||||
# Trailer headers will only be sent if the request specifies that we want
|
# Trailer headers will only be sent if the request specifies that we want
|
||||||
# them: http://tools.ietf.org/html/rfc2616#section-3.6.1
|
# them: http://tools.ietf.org/html/rfc2616#section-3.6.1
|
||||||
|
|
||||||
proc parseBody(client: PAsyncHttpClient,
|
proc parseBody(client: PAsyncHttpClient,
|
||||||
headers: PStringTable): Future[string] {.async.} =
|
headers: PStringTable): Future[string] {.async.} =
|
||||||
result = ""
|
result = ""
|
||||||
|
|
@ -549,7 +549,7 @@ proc parseBody(client: PAsyncHttpClient,
|
||||||
$length & " got " & $result.len)
|
$length & " got " & $result.len)
|
||||||
else:
|
else:
|
||||||
# (http://tools.ietf.org/html/rfc2616#section-4.4) NR.4 TODO
|
# (http://tools.ietf.org/html/rfc2616#section-4.4) NR.4 TODO
|
||||||
|
|
||||||
# -REGION- Connection: Close
|
# -REGION- Connection: Close
|
||||||
# (http://tools.ietf.org/html/rfc2616#section-4.4) NR.5
|
# (http://tools.ietf.org/html/rfc2616#section-4.4) NR.5
|
||||||
if headers["Connection"] == "close":
|
if headers["Connection"] == "close":
|
||||||
|
|
@ -598,7 +598,7 @@ proc parseResponse(client: PAsyncHttpClient,
|
||||||
inc(linei, le)
|
inc(linei, le)
|
||||||
if line[linei] != ':': httpError("invalid headers")
|
if line[linei] != ':': httpError("invalid headers")
|
||||||
inc(linei) # Skip :
|
inc(linei) # Skip :
|
||||||
|
|
||||||
result.headers[name] = line[linei.. -1].strip()
|
result.headers[name] = line[linei.. -1].strip()
|
||||||
if not fullyRead:
|
if not fullyRead:
|
||||||
httpError("Connection was closed before full request has been made")
|
httpError("Connection was closed before full request has been made")
|
||||||
|
|
@ -621,14 +621,14 @@ proc newConnection(client: PAsyncHttpClient, url: TURL) {.async.} =
|
||||||
else:
|
else:
|
||||||
rawsockets.TPort(80)
|
rawsockets.TPort(80)
|
||||||
else: rawsockets.TPort(url.port.parseInt)
|
else: rawsockets.TPort(url.port.parseInt)
|
||||||
|
|
||||||
if url.scheme.toLower() == "https":
|
if url.scheme.toLower() == "https":
|
||||||
when defined(ssl):
|
when defined(ssl):
|
||||||
client.sslContext.wrapSocket(client.socket)
|
client.sslContext.wrapSocket(client.socket)
|
||||||
else:
|
else:
|
||||||
raise newException(EHttpRequestErr,
|
raise newException(EHttpRequestErr,
|
||||||
"SSL support is not available. Cannot connect over SSL.")
|
"SSL support is not available. Cannot connect over SSL.")
|
||||||
|
|
||||||
await client.socket.connect(url.hostname, port)
|
await client.socket.connect(url.hostname, port)
|
||||||
client.currentURL = url
|
client.currentURL = url
|
||||||
client.connected = true
|
client.connected = true
|
||||||
|
|
@ -648,13 +648,13 @@ proc request*(client: PAsyncHttpClient, url: string, httpMethod = httpGET,
|
||||||
|
|
||||||
if not client.headers.hasKey("user-agent") and client.userAgent != "":
|
if not client.headers.hasKey("user-agent") and client.userAgent != "":
|
||||||
client.headers["User-Agent"] = client.userAgent
|
client.headers["User-Agent"] = client.userAgent
|
||||||
|
|
||||||
var headers = generateHeaders(r, httpMethod, client.headers)
|
var headers = generateHeaders(r, httpMethod, client.headers)
|
||||||
|
|
||||||
await client.socket.send(headers)
|
await client.socket.send(headers)
|
||||||
if body != "":
|
if body != "":
|
||||||
await client.socket.send(body)
|
await client.socket.send(body)
|
||||||
|
|
||||||
result = await parseResponse(client, httpMethod != httpHEAD)
|
result = await parseResponse(client, httpMethod != httpHEAD)
|
||||||
|
|
||||||
proc get*(client: PAsyncHttpClient, url: string): Future[TResponse] {.async.} =
|
proc get*(client: PAsyncHttpClient, url: string): Future[TResponse] {.async.} =
|
||||||
|
|
@ -676,7 +676,7 @@ when isMainModule:
|
||||||
proc main() {.async.} =
|
proc main() {.async.} =
|
||||||
var client = newAsyncHttpClient()
|
var client = newAsyncHttpClient()
|
||||||
var resp = await client.request("http://picheta.me")
|
var resp = await client.request("http://picheta.me")
|
||||||
|
|
||||||
echo("Got response: ", resp.status)
|
echo("Got response: ", resp.status)
|
||||||
echo("Body:\n")
|
echo("Body:\n")
|
||||||
echo(resp.body)
|
echo(resp.body)
|
||||||
|
|
@ -703,13 +703,13 @@ when isMainModule:
|
||||||
|
|
||||||
#var r = get("http://validator.w3.org/check?uri=http%3A%2F%2Fgoogle.com&
|
#var r = get("http://validator.w3.org/check?uri=http%3A%2F%2Fgoogle.com&
|
||||||
# charset=%28detect+automatically%29&doctype=Inline&group=0")
|
# charset=%28detect+automatically%29&doctype=Inline&group=0")
|
||||||
|
|
||||||
var headers: string = "Content-Type: multipart/form-data; boundary=xyz\c\L"
|
var headers: string = "Content-Type: multipart/form-data; boundary=xyz\c\L"
|
||||||
var body: string = "--xyz\c\L"
|
var body: string = "--xyz\c\L"
|
||||||
# soap 1.2 output
|
# soap 1.2 output
|
||||||
body.add("Content-Disposition: form-data; name=\"output\"\c\L")
|
body.add("Content-Disposition: form-data; name=\"output\"\c\L")
|
||||||
body.add("\c\Lsoap12\c\L")
|
body.add("\c\Lsoap12\c\L")
|
||||||
|
|
||||||
# html
|
# html
|
||||||
body.add("--xyz\c\L")
|
body.add("--xyz\c\L")
|
||||||
body.add("Content-Disposition: form-data; name=\"uploaded_file\";" &
|
body.add("Content-Disposition: form-data; name=\"uploaded_file\";" &
|
||||||
|
|
|
||||||
|
|
@ -428,7 +428,8 @@ proc close*(socket: Socket) =
|
||||||
elif res != 1:
|
elif res != 1:
|
||||||
socketError(socket)
|
socketError(socket)
|
||||||
|
|
||||||
proc toCInt(opt: SOBool): cint =
|
proc toCInt*(opt: SOBool): cint =
|
||||||
|
## Converts a ``SOBool`` into its Socket Option cint representation.
|
||||||
case opt
|
case opt
|
||||||
of OptAcceptConn: SO_ACCEPTCONN
|
of OptAcceptConn: SO_ACCEPTCONN
|
||||||
of OptBroadcast: SO_BROADCAST
|
of OptBroadcast: SO_BROADCAST
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue