Basic authorization implementation for HTTP client. (#204)
* Basic authorization implementation for HTTP client. Add tests for basic authorization. * Bump chronos version to 3.0.5.
This commit is contained in:
parent
f7dd6b76c2
commit
15137f71c3
|
@ -1,5 +1,5 @@
|
|||
packageName = "chronos"
|
||||
version = "3.0.4"
|
||||
version = "3.0.5"
|
||||
author = "Status Research & Development GmbH"
|
||||
description = "Chronos"
|
||||
license = "Apache License 2.0 or MIT"
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
# Apache License, version 2.0, (LICENSE-APACHEv2)
|
||||
# MIT license (LICENSE-MIT)
|
||||
import std/[uri, tables, strutils, sequtils]
|
||||
import stew/[results, base10], httputils
|
||||
import stew/[results, base10, base64], httputils
|
||||
import ../../asyncloop, ../../asyncsync
|
||||
import ../../streams/[asyncstream, tlsstream, chunkstream, boundstream]
|
||||
import httptable, httpcommon, httpagent, httpbodyrw, multipart
|
||||
|
@ -846,20 +846,26 @@ proc prepareRequest(request: HttpClientRequestRef): string {.
|
|||
toLowerAscii(request.headers.getString(TransferEncodingHeader)) == "chunked"
|
||||
|
||||
# We use ChronosIdent as `User-Agent` string if its not set.
|
||||
if UserAgentHeader notin request.headers:
|
||||
discard request.headers.hasKeyOrPut(UserAgentHeader, ChronosIdent)
|
||||
discard request.headers.hasKeyOrPut(UserAgentHeader, ChronosIdent)
|
||||
# We use request's hostname as `Host` string if its not set.
|
||||
if HostHeader notin request.headers:
|
||||
discard request.headers.hasKeyOrPut(HostHeader, request.address.hostname)
|
||||
discard request.headers.hasKeyOrPut(HostHeader, request.address.hostname)
|
||||
# We set `Connection` to value according to flags if its not set.
|
||||
if ConnectionHeader notin request.headers:
|
||||
if HttpClientRequestFlag.CloseConnection in request.flags:
|
||||
discard request.headers.hasKeyOrPut(ConnectionHeader, "close")
|
||||
request.headers.add(ConnectionHeader, "close")
|
||||
else:
|
||||
discard request.headers.hasKeyOrPut(ConnectionHeader, "keep-alive")
|
||||
request.headers.add(ConnectionHeader, "keep-alive")
|
||||
# We set `Accept` to accept any content if its not set.
|
||||
if AcceptHeader notin request.headers:
|
||||
discard request.headers.hasKeyOrPut(AcceptHeader, "*/*")
|
||||
discard request.headers.hasKeyOrPut(AcceptHeader, "*/*")
|
||||
|
||||
# We will send `Authorization` information only if username or password set,
|
||||
# and `Authorization` header is not present in request's headers.
|
||||
if len(request.address.username) > 0 or len(request.address.password) > 0:
|
||||
if AuthorizationHeader notin request.headers:
|
||||
let auth = request.address.username & ":" & request.address.password
|
||||
let header = "Basic " &
|
||||
Base64Pad.encode(auth.toOpenArrayByte(0, len(auth) - 1))
|
||||
request.headers.add(AuthorizationHeader, header)
|
||||
|
||||
# Here we perform automatic detection: if request was created with non-zero
|
||||
# body and `Content-Length` header is missing we will create one with size
|
||||
|
@ -867,7 +873,7 @@ proc prepareRequest(request: HttpClientRequestRef): string {.
|
|||
if ContentLengthHeader notin request.headers:
|
||||
if len(request.buffer) > 0:
|
||||
let slength = Base10.toString(uint64(len(request.buffer)))
|
||||
discard request.headers.hasKeyOrPut(ContentLengthHeader, slength)
|
||||
request.headers.add(ContentLengthHeader, slength)
|
||||
|
||||
request.bodyFlag =
|
||||
if ContentLengthHeader in request.headers:
|
||||
|
|
|
@ -30,6 +30,7 @@ const
|
|||
ExpectHeader* = "expect"
|
||||
ServerHeader* = "server"
|
||||
LocationHeader* = "location"
|
||||
AuthorizationHeader* = "authorization"
|
||||
|
||||
UrlEncodedContentType* = "application/x-www-form-urlencoded"
|
||||
MultipartContentType* = "multipart/form-data"
|
||||
|
|
|
@ -688,6 +688,17 @@ suite "HTTP client testing suite":
|
|||
await server.closeWait()
|
||||
return "redirect-" & $res
|
||||
|
||||
proc testBasicAuthorization(): Future[bool] {.async.} =
|
||||
var session = createSession(true, maxRedirections = 10)
|
||||
let url = parseUri("https://guest:guest@jigsaw.w3.org/HTTP/Basic/")
|
||||
let resp = await session.fetch(url)
|
||||
await session.closeWait()
|
||||
if (resp.status == 200) and
|
||||
("Your browser made it!" in cast[string](resp.data)):
|
||||
return true
|
||||
else:
|
||||
return false
|
||||
|
||||
test "HTTP all request methods test":
|
||||
let address = initTAddress("127.0.0.1:30080")
|
||||
check waitFor(testMethods(address, false)) == 18
|
||||
|
@ -752,6 +763,9 @@ suite "HTTP client testing suite":
|
|||
let address = initTAddress("127.0.0.1:30080")
|
||||
check waitFor(testRequestRedirectTest(address, true, 4)) == "redirect-true"
|
||||
|
||||
test "HTTPS basic authorization test":
|
||||
check waitFor(testBasicAuthorization()) == true
|
||||
|
||||
test "Leaks test":
|
||||
proc getTrackerLeaks(tracker: string): bool =
|
||||
let tracker = getTracker(tracker)
|
||||
|
|
Loading…
Reference in New Issue