Skip to content

Commit

Permalink
Merge pull request #97 from its5Q/response-uri
Browse files Browse the repository at this point in the history
Add url field to Response
  • Loading branch information
treeform authored Jan 16, 2023
2 parents affc4b2 + 3f308e4 commit 0115db0
Show file tree
Hide file tree
Showing 8 changed files with 65 additions and 3 deletions.
1 change: 1 addition & 0 deletions src/puppy/common.nim
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ type

Response* = ref object
headers*: HttpHeaders
url*: string
code*: int
body*: string

Expand Down
10 changes: 8 additions & 2 deletions src/puppy/platforms/linux/platform.nim
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ proc fetch*(req: Request): Response {.raises: [PuppyError].} =
strings.add k & ": " & v

let curl = easy_init()
defer:
curl.easy_cleanup()

discard curl.easy_setopt(OPT_URL, strings[0].cstring)
discard curl.easy_setopt(OPT_CUSTOMREQUEST, strings[1].cstring)
Expand Down Expand Up @@ -92,16 +94,20 @@ proc fetch*(req: Request): Response {.raises: [PuppyError].} =
ret = curl.easy_perform()
headerData = headerWrap.str

curl.easy_cleanup()

if ret == E_OK:
var httpCode: uint32
discard curl.easy_getinfo(INFO_RESPONSE_CODE, httpCode.addr)
result.code = httpCode.int

var responseUrl: cstring
discard curl.easy_getinfo(INFO_EFFECTIVE_URL, responseUrl.addr)
result.url = $responseUrl

for headerLine in headerData.split(CRLF):
let arr = headerLine.split(":", 1)
if arr.len == 2:
result.headers.add((arr[0].strip(), arr[1].strip()))

result.body = bodyWrap.str
if result.headers["Content-Encoding"] == "gzip":
try:
Expand Down
2 changes: 2 additions & 0 deletions src/puppy/platforms/macos/macdefs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,5 @@ objc:
): NSData
proc statusCode*(self: NSHTTPURLResponse): int
proc allHeaderFields*(self: NSHTTPURLResponse): NSDictionary
proc URL*(self: NSHTTPURLResponse): NSURL
proc absoluteString*(self: NSURL): NSString
2 changes: 2 additions & 0 deletions src/puppy/platforms/macos/platform.nim
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ proc fetch*(req: Request): Response {.raises: [PuppyError].} =
if response.int != 0:
result.code = response.statusCode

result.url = $(response.URL.absoluteString)

let
dictionary = response.allHeaderFields
keyEnumerator = dictionary.keyEnumerator
Expand Down
31 changes: 30 additions & 1 deletion src/puppy/platforms/win32/platform.nim
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,35 @@ proc fetch*(req: Request): Response {.raises: [PuppyError].} =
)

result.code = statusCode
var
responseUrlBytes: DWORD
responseUrlBuf: string

# Determine how big the URL buffer needs to be
discard WinHttpQueryOption(
hRequest,
WINHTTP_OPTION_URL,
nil,
responseUrlBytes.addr
)
var errorCode = GetLastError()
if errorCode == ERROR_INSUFFICIENT_BUFFER: # Expected!
# Set the URL buffer to the correct size and inclue a null terminator
responseUrlBuf.setLen(responseUrlBytes)
else:
raise newException(PuppyError, "WinHttpQueryOption error: " & $errorCode)

# Read the URL into the buffer
if WinHttpQueryOption(
hRequest,
WINHTTP_OPTION_URL,
responseUrlBuf[0].addr,
responseUrlBytes.addr,
) == 0:
raise newException(PuppyError, "WinHttpQueryOption error: " & $errorCode)

result.url = $cast[ptr WCHAR](responseUrlBuf[0].addr)

var
responseHeaderBytes: DWORD
responseHeaderBuf: string
Expand All @@ -196,7 +225,7 @@ proc fetch*(req: Request): Response {.raises: [PuppyError].} =
responseHeaderBytes.addr,
nil
)
let errorCode = GetLastError()
errorCode = GetLastError()
if errorCode == ERROR_INSUFFICIENT_BUFFER: # Expected!
# Set the header buffer to the correct size and inclue a null terminator
responseHeaderBuf.setLen(responseHeaderBytes)
Expand Down
8 changes: 8 additions & 0 deletions src/puppy/platforms/win32/windefs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ const
ERROR_INTERNET_SEC_CERT_REVOKED* = 12170

WINHTTP_OPTION_SECURITY_FLAGS* = 31
WINHTTP_OPTION_URL* = 34
SECURITY_FLAG_IGNORE_UNKNOWN_CA* = 0x00000100
# SECURITY_FLAG_IGNORE_WRONG_USAGE* = 0x00000200
SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE* = 0x00000200
Expand Down Expand Up @@ -140,6 +141,13 @@ proc WinHttpQueryHeaders*(
lpdwIndex: LPDWORD
): BOOL {.dynlib: "winhttp".}

proc WinHttpQueryOption*(
hRequest: HINTERNET,
dwOption: DWORD,
lpBuffer: LPVOID,
lpdwBufferLength: LPDWORD,
): BOOL {.dynlib: "winhttp".}

proc WinHttpReadData*(
hFile: HINTERNET,
lpBuffer: LPVOID,
Expand Down
5 changes: 5 additions & 0 deletions tests/debug_server.nim
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ proc cb(req: Request) {.async.} =
await req.respond(Http200, $req.url, headers)
return

if req.url.path == "/redirect":
let headers = newHttpHeaders([("Location", "/ok")])
await req.respond(Http301, "", headers)
return

await req.respond(Http404, "Not found.")

waitFor server.serve(Port(8080), cb)
9 changes: 9 additions & 0 deletions tests/test.nim
Original file line number Diff line number Diff line change
Expand Up @@ -194,5 +194,14 @@ try:
doAssert res.headers["1"] == "a"
doAssert res.headers["2"] == "b"

block:
# test redirect
let res = fetch(Request(
url: parseUrl("http://localhost:8080/redirect"),
verb: "get",
))
doAssert res.code == 200
doAssert res.url == "http://localhost:8080/ok"

finally:
debugServer.terminate()

0 comments on commit 0115db0

Please sign in to comment.