Merge pull request #1743 from cowboy-coders/httpclient_net_module
Switch httpclient to use net module instead of sockets
This commit is contained in:
commit
2024ca454f
1 changed files with 15 additions and 17 deletions
|
|
@ -88,10 +88,9 @@
|
||||||
## constructor should be used for this purpose. However,
|
## constructor should be used for this purpose. However,
|
||||||
## currently only basic authentication is supported.
|
## currently only basic authentication is supported.
|
||||||
|
|
||||||
import sockets, strutils, parseurl, parseutils, strtabs, base64, os
|
import net, strutils, uri, parseutils, strtabs, base64, os
|
||||||
import asyncnet, asyncdispatch
|
import asyncnet, asyncdispatch
|
||||||
import rawsockets
|
import rawsockets
|
||||||
from net import nil
|
|
||||||
|
|
||||||
type
|
type
|
||||||
Response* = tuple[
|
Response* = tuple[
|
||||||
|
|
@ -101,7 +100,7 @@ type
|
||||||
body: string]
|
body: string]
|
||||||
|
|
||||||
Proxy* = ref object
|
Proxy* = ref object
|
||||||
url*: Url
|
url*: Uri
|
||||||
auth*: string
|
auth*: string
|
||||||
|
|
||||||
ProtocolError* = object of IOError ## exception that is raised when server
|
ProtocolError* = object of IOError ## exception that is raised when server
|
||||||
|
|
@ -279,7 +278,7 @@ else:
|
||||||
|
|
||||||
proc newProxy*(url: string, auth = ""): Proxy =
|
proc newProxy*(url: string, auth = ""): Proxy =
|
||||||
## Constructs a new ``TProxy`` object.
|
## Constructs a new ``TProxy`` object.
|
||||||
result = Proxy(url: parseUrl(url), auth: auth)
|
result = Proxy(url: parseUri(url), auth: auth)
|
||||||
|
|
||||||
proc request*(url: string, httpMethod = httpGET, extraHeaders = "",
|
proc request*(url: string, httpMethod = httpGET, extraHeaders = "",
|
||||||
body = "",
|
body = "",
|
||||||
|
|
@ -290,7 +289,7 @@ proc request*(url: string, httpMethod = httpGET, extraHeaders = "",
|
||||||
## | Extra headers can be specified and must be seperated by ``\c\L``
|
## | Extra headers can be specified and must be seperated by ``\c\L``
|
||||||
## | An optional timeout can be specified in miliseconds, if reading from the
|
## | An optional timeout can be specified in miliseconds, if reading from the
|
||||||
## server takes longer than specified an ETimeout exception will be raised.
|
## server takes longer than specified an ETimeout exception will be raised.
|
||||||
var r = if proxy == nil: parseUrl(url) else: proxy.url
|
var r = if proxy == nil: parseUri(url) else: proxy.url
|
||||||
var headers = substr($httpMethod, len("http"))
|
var headers = substr($httpMethod, len("http"))
|
||||||
if proxy == nil:
|
if proxy == nil:
|
||||||
headers.add(" /" & r.path & r.query)
|
headers.add(" /" & r.path & r.query)
|
||||||
|
|
@ -308,18 +307,18 @@ proc request*(url: string, httpMethod = httpGET, extraHeaders = "",
|
||||||
add(headers, extraHeaders)
|
add(headers, extraHeaders)
|
||||||
add(headers, "\c\L")
|
add(headers, "\c\L")
|
||||||
|
|
||||||
var s = socket()
|
var s = newSocket()
|
||||||
if s == invalidSocket: raiseOSError(osLastError())
|
if s == nil: raiseOSError(osLastError())
|
||||||
var port = sockets.Port(80)
|
var port = net.Port(80)
|
||||||
if r.scheme == "https":
|
if r.scheme == "https":
|
||||||
when defined(ssl):
|
when defined(ssl):
|
||||||
sslContext.wrapSocket(s)
|
sslContext.wrapSocket(s)
|
||||||
port = sockets.Port(443)
|
port = net.Port(443)
|
||||||
else:
|
else:
|
||||||
raise newException(HttpRequestError,
|
raise newException(HttpRequestError,
|
||||||
"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.Port(r.port.parseInt)
|
port = net.Port(r.port.parseInt)
|
||||||
|
|
||||||
if timeout == -1:
|
if timeout == -1:
|
||||||
s.connect(r.hostname, port)
|
s.connect(r.hostname, port)
|
||||||
|
|
@ -342,9 +341,9 @@ proc getNewLocation(lastUrl: string, headers: StringTableRef): string =
|
||||||
result = headers["Location"]
|
result = headers["Location"]
|
||||||
if result == "": httpError("location header expected")
|
if result == "": httpError("location header expected")
|
||||||
# Relative URLs. (Not part of the spec, but soon will be.)
|
# Relative URLs. (Not part of the spec, but soon will be.)
|
||||||
let r = parseURL(result)
|
let r = parseUri(result)
|
||||||
if r.hostname == "" and r.path != "":
|
if r.hostname == "" and r.path != "":
|
||||||
let origParsed = parseURL(lastUrl)
|
let origParsed = parseUri(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,
|
||||||
|
|
@ -437,7 +436,7 @@ proc downloadFile*(url: string, outputFilename: string,
|
||||||
else:
|
else:
|
||||||
fileError("Unable to open file")
|
fileError("Unable to open file")
|
||||||
|
|
||||||
proc generateHeaders(r: Url, httpMethod: HttpMethod,
|
proc generateHeaders(r: Uri, httpMethod: HttpMethod,
|
||||||
headers: StringTableRef): string =
|
headers: StringTableRef): string =
|
||||||
result = substr($httpMethod, len("http"))
|
result = substr($httpMethod, len("http"))
|
||||||
# TODO: Proxies
|
# TODO: Proxies
|
||||||
|
|
@ -455,7 +454,7 @@ type
|
||||||
AsyncHttpClient* = ref object
|
AsyncHttpClient* = ref object
|
||||||
socket: AsyncSocket
|
socket: AsyncSocket
|
||||||
connected: bool
|
connected: bool
|
||||||
currentURL: Url ## Where we are currently connected.
|
currentURL: Uri ## Where we are currently connected.
|
||||||
headers*: StringTableRef
|
headers*: StringTableRef
|
||||||
maxRedirects: int
|
maxRedirects: int
|
||||||
userAgent: string
|
userAgent: string
|
||||||
|
|
@ -499,7 +498,6 @@ proc recvFull(socket: AsyncSocket, size: int): Future[string] {.async.} =
|
||||||
|
|
||||||
proc parseChunks(client: AsyncHttpClient): Future[string] {.async.} =
|
proc parseChunks(client: AsyncHttpClient): Future[string] {.async.} =
|
||||||
result = ""
|
result = ""
|
||||||
var ri = 0
|
|
||||||
while true:
|
while true:
|
||||||
var chunkSize = 0
|
var chunkSize = 0
|
||||||
var chunkSizeStr = await client.socket.recvLine()
|
var chunkSizeStr = await client.socket.recvLine()
|
||||||
|
|
@ -607,7 +605,7 @@ proc parseResponse(client: AsyncHttpClient,
|
||||||
else:
|
else:
|
||||||
result.body = ""
|
result.body = ""
|
||||||
|
|
||||||
proc newConnection(client: AsyncHttpClient, url: Url) {.async.} =
|
proc newConnection(client: AsyncHttpClient, url: Uri) {.async.} =
|
||||||
if client.currentURL.hostname != url.hostname or
|
if client.currentURL.hostname != url.hostname or
|
||||||
client.currentURL.scheme != url.scheme:
|
client.currentURL.scheme != url.scheme:
|
||||||
if client.connected: client.close()
|
if client.connected: client.close()
|
||||||
|
|
@ -643,7 +641,7 @@ proc request*(client: AsyncHttpClient, url: string, httpMethod = httpGET,
|
||||||
## connection can be closed by using the ``close`` procedure.
|
## connection can be closed by using the ``close`` procedure.
|
||||||
##
|
##
|
||||||
## The returned future will complete once the request is completed.
|
## The returned future will complete once the request is completed.
|
||||||
let r = parseUrl(url)
|
let r = parseUri(url)
|
||||||
await newConnection(client, r)
|
await newConnection(client, r)
|
||||||
|
|
||||||
if not client.headers.hasKey("user-agent") and client.userAgent != "":
|
if not client.headers.hasKey("user-agent") and client.userAgent != "":
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue