Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft for adding insecure certificates option #68

Merged
merged 21 commits into from
Aug 26, 2022
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions src/puppy.nim
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,17 @@ proc newRequest*(
url: string,
verb = "get",
headers = newSeq[Header](),
timeout: float32 = 60
timeout: float32 = 60,
insecure: bool = false,
): Request =
## Allocates a new request object with defaults.
result = Request()
result.url = parseUrl(url)
result.verb = verb
result.headers = headers
result.timeout = timeout

result.insecure = insecure
guzba marked this conversation as resolved.
Show resolved Hide resolved

proc fetch*(url: string, headers = newSeq[Header]()): string =
let
req = newRequest(url, "get", headers)
Expand Down
12 changes: 3 additions & 9 deletions src/puppy/common.nim
Original file line number Diff line number Diff line change
@@ -1,35 +1,30 @@
import urlly, strutils

guzba marked this conversation as resolved.
Show resolved Hide resolved
export urlly

const CRLF* = "\r\n"

type
Header* = object
key*: string
value*: string

Request* = ref object
url*: Url
headers*: seq[Header]
timeout*: float32
verb*: string
body*: string
when defined(puppyLibcurl) or (defined(windows) or not defined(macosx)):
allowAnyHttpsCertificate*: bool

Response* = ref object
headers*: seq[Header]
code*: int
body*: string

PuppyError* = object of IOError ## Raised if an operation fails.

proc `[]`*(headers: seq[Header], key: string): string =
## Get a key out of headers. Not case sensitive.
## Use a for loop to get multiple keys.
for header in headers:
if header.key.toLowerAscii() == key.toLowerAscii():
return header.value

proc `[]=`*(headers: var seq[Header], key, value: string) =
## Sets a key in the headers. Not case sensitive.
## If key is not there appends a new key-value pair at the end.
Expand All @@ -38,6 +33,5 @@ proc `[]=`*(headers: var seq[Header], key, value: string) =
header.value = value
return
headers.add(Header(key: key, value: value))

proc `$`*(req: Request): string =
req.verb.toUpperAscii & " " & $req.url
req.verb.toUpperAscii & " " & $req.url
30 changes: 16 additions & 14 deletions src/puppy/platforms/linux/platform.nim
Original file line number Diff line number Diff line change
Expand Up @@ -16,29 +16,27 @@ proc fetch*(req: Request): Response {.raises: [PuppyError].} =
count: int,
outstream: pointer
): int {.cdecl.} =
if size != 1:
raise newException(PuppyError, "Unexpected curl write callback size")
let
outbuf = cast[ptr StringWrap](outstream)
i = outbuf.str.len
outbuf.str.setLen(outbuf.str.len + count)
copyMem(outbuf.str[i].addr, buffer, count)
result = size * count

{.pop.}

var strings: seq[string]
strings.add $req.url
strings.add req.verb.toUpperAscii()
for header in req.headers:
strings.add header.key & ": " & header.value

let curl = easy_init()

discard curl.easy_setopt(OPT_URL, strings[0].cstring)
discard curl.easy_setopt(OPT_CUSTOMREQUEST, strings[1].cstring)
discard curl.easy_setopt(OPT_TIMEOUT, req.timeout.int)

# Create the Pslist for passing headers to curl manually. This is to
# avoid needing to call slist_free_all which creates problems
var slists: seq[Slist]
Expand All @@ -54,32 +52,36 @@ proc fetch*(req: Request): Response {.raises: [PuppyError].} =
while tail.next != nil:
tail = tail.next
tail.next = slists[i].addr

discard curl.easy_setopt(OPT_HTTPHEADER, headerList)

if req.verb.toUpperAscii() == "POST" or req.body.len > 0:
discard curl.easy_setopt(OPT_POSTFIELDSIZE, req.body.len)
discard curl.easy_setopt(OPT_POSTFIELDS, req.body.cstring)

# Setup writers.
var headerWrap, bodyWrap: StringWrap
discard curl.easy_setopt(OPT_WRITEDATA, bodyWrap.addr)
discard curl.easy_setopt(OPT_WRITEFUNCTION, curlWriteFn)
discard curl.easy_setopt(OPT_HEADERDATA, headerWrap.addr)
discard curl.easy_setopt(OPT_HEADERFUNCTION, curlWriteFn)

# On windows look for cacert.pem.
when defined(windows):
discard curl.easy_setopt(OPT_CAINFO, "cacert.pem".cstring)
# Follow redirects by default.
discard curl.easy_setopt(OPT_FOLLOWLOCATION, 1)

if req.allowAnyHttpsCertificate:
discard curl.easy_setopt(OPT_SSL_VERIFYPEER, 0)
discard curl.easy_setopt(OPT_SSL_VERIFYHOST, 0)

let
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)
Expand All @@ -95,4 +97,4 @@ proc fetch*(req: Request): Response {.raises: [PuppyError].} =
except ZippyError as e:
raise newException(PuppyError, "Error uncompressing response", e)
else:
raise newException(PuppyError, $easy_strerror(ret))
raise newException(PuppyError, $easy_strerror(ret))
1 change: 1 addition & 0 deletions src/puppy/platforms/macos/macdefs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ objc:
proc setHTTPMethod*(self: NSMutableURLRequest, _: NSString)
proc setValue*(self: NSMutableURLRequest, _: NSString, forHTTPHeaderField: NSString)
proc setHTTPBody*(self: NSMutableURLRequest, _: NSData)
proc setAllowsAnyHTTPSCertificate*(self: NSMutableURLRequest)
guzba marked this conversation as resolved.
Show resolved Hide resolved
guzba marked this conversation as resolved.
Show resolved Hide resolved
proc sendSynchronousRequest*(
class: typedesc[NSURLConnection],
_: NSMutableURLRequest,
Expand Down
3 changes: 3 additions & 0 deletions src/puppy/platforms/macos/platform.nim
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ proc fetch*(req: Request): Response {.raises: [PuppyError].} =
if req.body.len > 0:
request.setHTTPBody(NSData.dataWithBytes(req.body[0].addr, req.body.len))

if req.insecure:
request.setAllowsAnyHTTPSCertificate()
guzba marked this conversation as resolved.
Show resolved Hide resolved

var
response: NSHTTPURLResponse
error: NSError
Expand Down
Loading