std/httpclient
SourceEditЭтот модуль реализует простой HTTP-клиент, который можно использовать для получения веб-страниц и других данных.
Получение веб-сайта
В этом примере используется HTTP GET для получения http://google.com:
import std/httpclient
var client = newHttpClient()
try:
echo client.getContent("http://google.com")
finally:
client.close() То же действие можно выполнить асинхронно, просто используйте AsyncHttpClient:
import std/[asyncdispatch, httpclient]
proc asyncProc(): Future[string] {.async.} =
var client = newAsyncHttpClient()
try:
return await client.getContent("http://google.com")
finally:
client.close()
echo waitFor asyncProc() Функциональность, реализованная HttpClient и AsyncHttpClient, одинаковая, поэтому вы можете использовать ту, которая вам больше подходит в показанных здесь примерах.
Примечание: Вам необходимо запускать асинхронные примеры в асинхронной процедуре, иначе вы получите ошибку Undeclared identifier: 'await'.
Примечание: Экземпляр асинхронного клиента может обрабатывать только один запрос за раз. Чтобы отправить несколько запросов параллельно, используйте несколько экземпляров клиента.
Использование HTTP POST
Этот пример демонстрирует использование W3 HTML Validator, он использует multipart/form-data в качестве Content-Type для отправки HTML для валидации на сервер.
var client = newHttpClient()
var data = newMultipartData()
data["output"] = "soap12"
data["uploaded_file"] = ("test.html", "text/html",
"<html><head></head><body><p>test</p></body></html>")
try:
echo client.postContent("http://validator.w3.org/check", multipart=data)
finally:
client.close() Чтобы передавать файлы с диска при выполнении запроса, используйте addFiles.
Примечание: Это будет выделять новую базу данных Mimetypes каждый раз, когда вы ее вызываете; вы можете передать свою собственную через параметр mimeDb чтобы этого избежать.
let mimes = newMimetypes()
var client = newHttpClient()
var data = newMultipartData()
data.addFiles({"uploaded_file": "test.html"}, mimeDb = mimes)
try:
echo client.postContent("http://validator.w3.org/check", multipart=data)
finally:
client.close() Вы также можете отправлять запросы POST с настраиваемыми заголовками. В этом примере устанавливается Content-Type в application/json и используется json-объект для тела
import std/[httpclient, json]
let client = newHttpClient()
client.headers = newHttpHeaders({ "Content-Type": "application/json" })
let body = %*{
"data": "some text"
}
try:
let response = client.request("http://some.api", httpMethod = HttpPost, body = $body)
echo response.status
finally:
client.close() Отчёт о ходе выполнения
Вы можете указать процедуру обратного вызова, которая будет вызываться во время HTTP-запроса. Этот обратный вызов будет выполняться каждую секунду с информацией о ходе выполнения HTTP-запроса.
import std/[asyncdispatch, httpclient]
proc onProgressChanged(total, progress, speed: BiggestInt) {.async.} =
echo("Downloaded ", progress, " of ", total)
echo("Current rate: ", speed div 1000, "kb/s")
proc asyncProc() {.async.} =
var client = newAsyncHttpClient()
client.onProgressChanged = onProgressChanged
try:
discard await client.getContent("http://speedtest-ams2.digitalocean.com/100mb.test")
finally:
client.close()
waitFor asyncProc() Если вы хотите удалить обратный вызов, просто установите его в nil.
client.onProgressChanged = nil
total , сообщаемое httpclient, может быть 0 в некоторых случаях.Поддержка SSL/TLS
Для этого требуется библиотека OpenSSL. К счастью, она широко используется и установлена на многих операционных системах. httpclient будет автоматически использовать SSL, если вы передадите любую из функций URL со схемой https, например: https://github.com/.
Вам также необходимо скомпилировать с ssl заданным так: nim c -d:ssl ....
Проверка сертификата выполняется по умолчанию.
Сканируется набор каталогов и файлов из модуля ssl_certs для поиска сертификатов CA.
Пример настройки параметров проверки SSL в новом клиенте:
import httpclient var client = newHttpClient(sslContext=newContext(verifyMode=CVerifyPeer))
Существует три варианта режима проверки:
-
CVerifyNone: сертификаты не проверяются; -
CVerifyPeer: сертификаты проверяются; -
CVerifyPeerUseEnvVars: сертификаты проверяются, и также используются необязательные переменные среды SSL_CERT_FILE и SSL_CERT_DIR для поиска сертификатов
См. newContext для настройки или отключения проверки сертификатов.
Таймауты
В настоящее время таймаут поддерживается только для синхронных функций. Таймаут измеряется в миллисекундах; после его установки любой вызов сокета, который может заблокироваться, будет подвержен этому таймауту.
Может показаться удивительным, но функция в целом может занимать больше времени, чем указанный таймаут; только отдельные внутренние вызовы сокета затронуты. На практике это означает, что пока сервер отправляет данные, исключение не будет сгенерировано, однако, если данные не достигнут клиента в течение указанного таймаута, будет сгенерировано исключение TimeoutError.
Вот как установить таймаут при создании экземпляра HttpClient:
import std/httpclient let client = newHttpClient(timeout = 42)
Прокси
Прокси можно указать как параметр любой из процедур, определенных в этом модуле. Для этого используйте конструктор newProxy. К сожалению, в настоящее время поддерживается только базовая аутентификация.
Некоторые примеры настройки прокси для HttpClient:
import std/httpclient
let myProxy = newProxy("http://myproxy.network")
let client = newHttpClient(proxy = myProxy) Использование прокси с базовой аутентификацией:
import std/httpclient
let myProxy = newProxy("http://myproxy.network", auth="user:password")
let client = newHttpClient(proxy = myProxy) Получение URL прокси из переменных среды:
import std/httpclient
var url = ""
try:
if existsEnv("http_proxy"):
url = getEnv("http_proxy")
elif existsEnv("https_proxy"):
url = getEnv("https_proxy")
except ValueError:
echo "Unable to parse proxy from environment variables."
let myProxy = newProxy(url = url)
let client = newHttpClient(proxy = myProxy) Перенаправления
Максимальное количество перенаправлений можно установить с помощью параметра maxRedirects типа int. Он определяет максимальное количество перенаправлений, которые следует отслеживать; по умолчанию он равен 5, вы можете установить его в 0 для отключения перенаправлений.
Здесь вы можете увидеть пример установки параметра maxRedirects для HttpClient:
import std/httpclient let client = newHttpClient(maxRedirects = 0)
Импорты
- since, net, strutils, uri, parseutils, base64, os, mimetypes, math, random, httpcore, times, tables, streams, monotimes, asyncnet, asyncdispatch, asyncfile, nativesockets
Типы
AsyncResponse = ref object version*: string status*: string headers*: HttpHeaders bodyStream*: FutureStream[string]
- Source Edit
HttpClientBase[SocketType] = ref object ## Where we are currently connected. headers*: HttpHeaders ## Headers to send in requests. ## Maximum redirects, set to `0` to disable. timeout*: int ## Only used for blocking HttpClient for now. ## `nil` or the callback to call when request progress changes. when SocketType is Socket: onProgressChanged*: ProgressChangedProc[void] else: onProgressChanged*: ProgressChangedProc[Future[void]] when defined(ssl): when SocketType is AsyncSocket: else: ## When `false`, the body is never read in requestAux.- Source Edit
HttpRequestError = object of IOError
- Выбрасывается в процедуре
getContentиpostContentпри получении от сервера ошибки Source Edit ProgressChangedProc[ReturnType] = proc (total, progress, speed: BiggestInt): ReturnType {. closure, ...gcsafe.}- Source Edit
Константы
Процедуры
proc `$`(data: MultipartData): string {....raises: [], tags: [], forbids: [].}- преобразовать MultipartData в строку, чтобы она была удобочитаемой при выводе https://github.com/nim-lang/Nim/issues/11863 Исходный код Редактировать
proc `[]=`(p: MultipartData; name, content: string) {.inline, ...raises: [ValueError], tags: [], forbids: [].}-
Добавить элемент multipart в данные multipart
p. Значение добавляется без имени файла и без типа содержимого.data["username"] = "NimUser"
Исходный код Редактировать proc `[]=`(p: MultipartData; name: string; file: tuple[name, contentType, content: string]) {.inline, ...raises: [ValueError], tags: [], forbids: [].}-
Добавить файл в данные multipart
p, указав имя файла, contentType и содержимое вручную.data["uploaded_file"] = ("test.html", "text/html", "<html><head></head><body><p>test</p></body></html>")Исходный код Редактировать proc add(p: MultipartData; name, content: string; filename: string = ""; contentType: string = ""; useStream = true) {....raises: [ValueError], tags: [], forbids: [].}-
Добавить значение в данные multipart.
Когда
useStreamравноfalse, файл будет прочитан в память.Вызывается исключение
Исходный код РедактироватьValueErrorеслиname,filenameилиcontentTypeсодержат символы новой строки. proc add(p: MultipartData; xs: MultipartEntries): MultipartData {.discardable, ...raises: [ValueError], tags: [], forbids: [].}-
Добавить список элементов multipart в данные multipart
p. Все значения добавляются без имени файла и без типа содержимого.data.add({"action": "login", "format": "json"})Исходный код Редактировать proc addFiles(p: MultipartData; xs: openArray[tuple[name, file: string]]; mimeDb = newMimetypes(); useStream = true): MultipartData {. discardable, ...raises: [IOError, ValueError], tags: [ReadIOEffect], forbids: [].}-
Добавить файлы в объект multipart data. Файлы будут передаваться из диска, когда запрос обрабатывается. Когда
streamравноfalse, файлы вместо этого считываются в память, но следует учитывать, что это очень неэффективно с точки зрения памяти даже для небольших файлов. Типы MIME будут определяться автоматически. Вызывается исключениеIOErrorесли файл не может быть открыт или считывание завершается ошибкой. Чтобы вручную указать содержимое файла, имя файла и тип MIME, используйте[]=.data.addFiles({"uploaded_file": "public/test.html"})Исходный код Редактировать proc body(response: AsyncResponse): Future[string] {....stackTrace: false, raises: [Exception, ValueError], tags: [RootEffect], forbids: [].}- Считывает тело ответа и кеширует его. Чтение выполняется только один раз. Исходный код Редактировать
proc body(response: Response): string {....raises: [IOError, OSError], tags: [ReadIOEffect], forbids: [].}-
Получает тело указанного ответа.
Поток тела ответа считывается синхронно.
Исходный код Редактировать proc close(client: HttpClient | AsyncHttpClient)
- Закрывает все соединения, используемые HTTP-клиентом. Исходный код Редактировать
proc code(response: Response | AsyncResponse): HttpCode {. ...raises: [ValueError, OverflowDefect].}-
Получает указанный
HttpCodeответа.Вызывает исключение
Исходный код РедактироватьValueErrorеслиstatusответа не имеет соответствующегоHttpCode. proc contentLength(response: Response | AsyncResponse): int
-
Получает длину содержимого указанного ответа.
Это фактически значение заголовка "Content-Length".
Исключение
Исходный код РедактироватьValueErrorбудет вызвано, если значение не является целым числом. Если заголовок Content-Length не задан в ответе, ContentLength устанавливается в значение -1. proc contentType(response: Response | AsyncResponse): string {.inline.}-
Получает тип содержимого указанного ответа.
Это фактически значение заголовка "Content-Type".
Исходный код Редактировать proc delete(client: AsyncHttpClient; url: Uri | string): Future[AsyncResponse] {. ...stackTrace: false.}- Подключается к хосту, указанному в URL, и выполняет запрос DELETE. Эта процедура использует значения httpClient, такие как
client.maxRedirects. Исходный код Редактировать proc delete(client: HttpClient; url: Uri | string): Response
- Исходный код Редактировать
proc deleteContent(client: AsyncHttpClient; url: Uri | string): Future[string] {. ...stackTrace: false.}- Подключается к хосту, указанному в URL, и возвращает содержимое запроса DELETE. Исходный код Редактировать
proc deleteContent(client: HttpClient; url: Uri | string): string
- Исходный код Редактировать
proc downloadFile(client: AsyncHttpClient; url: Uri | string; filename: string): Future[ void]- Исходный код Редактировать
proc downloadFile(client: HttpClient; url: Uri | string; filename: string)
- Скачивает
urlи сохраняет его вfilename. Исходный код Редактировать proc get(client: AsyncHttpClient; url: Uri | string): Future[AsyncResponse] {. ...stackTrace: false.}-
Подключается к хосту, указанному в URL, и выполняет запрос GET.
Эта процедура использует значения httpClient, такие как
Исходный код Редактироватьclient.maxRedirects. proc get(client: HttpClient; url: Uri | string): Response
- Исходный код Редактировать
proc getContent(client: AsyncHttpClient; url: Uri | string): Future[string] {. ...stackTrace: false.}- Подключается к хосту, указанному в URL, и возвращает содержимое запроса GET. Исходный код Редактировать
proc getContent(client: HttpClient; url: Uri | string): string
- Исходный код Редактировать
proc getSocket(client: AsyncHttpClient): AsyncSocket {.inline, ...raises: [], tags: [], forbids: [].}- Исходный код Редактировать
proc getSocket(client: HttpClient): Socket {.inline, ...raises: [], tags: [], forbids: [].}-
Получить сетевой сокет, полезно, если вы хотите получить более подробную информацию о соединении.
Этот пример показывает информацию о локальных и удаленных конечных точках:
if client.connected: echo client.getSocket.getLocalAddr echo client.getSocket.getPeerAddr
Исходный код Редактировать
proc head(client: AsyncHttpClient; url: Uri | string): Future[AsyncResponse] {. ...stackTrace: false.}-
Подключается к хосту, указанному в URL, и выполняет запрос HEAD.
Эта процедура использует значения httpClient, такие как
Исходный код Изменитьclient.maxRedirects. proc head(client: HttpClient; url: Uri | string): Response
- Исходный код Изменить
proc lastModified(response: Response | AsyncResponse): DateTime
-
Получает время последнего изменения указанного ответа.
Эффективно, это значение заголовка «Last-Modified».
Вызывает
Исходный код ИзменитьValueErrorесли разбор не удался или значение не является правильно отформатированной датой и временем. proc newAsyncHttpClient(userAgent = defUserAgent; maxRedirects = 5; sslContext = getDefaultSSL(); proxy: Proxy = nil; headers = newHttpHeaders()): AsyncHttpClient {. ...raises: [], tags: [], forbids: [].}-
Создаёт новый экземпляр AsyncHttpClient.
userAgentопределяет пользовательский агент, который будет использоваться при выполнении запросов.maxRedirectsопределяет максимальное количество переадресаций, которые будут следовать, по умолчанию 5.sslContextопределяет контекст SSL для использования в запросах HTTPS.proxyопределяет прокси HTTP для подключений этого HTTP-клиента.headersопределяет HTTP-заголовки.Пример:
import std/[asyncdispatch, strutils] proc asyncProc(): Future[string] {.async.} = let client = newAsyncHttpClient() result = await client.getContent("http://example.com") let exampleHtml = waitFor asyncProc() assert "Example Domain" in exampleHtml assert "Pizza" notin exampleHtmlИсходный код Изменить proc newHttpClient(userAgent = defUserAgent; maxRedirects = 5; sslContext = getDefaultSSL(); proxy: Proxy = nil; timeout = -1; headers = newHttpHeaders()): HttpClient {. ...raises: [], tags: [], forbids: [].}-
Создаёт новый экземпляр HttpClient.
userAgentопределяет пользовательский агент, который будет использоваться при выполнении запросов.maxRedirectsопределяет максимальное количество переадресаций, которые будут следовать, по умолчанию 5.sslContextопределяет контекст SSL для использования в запросах HTTPS. См. Поддержка SSL/TLSproxyопределяет прокси HTTP для подключений этого HTTP-клиента.timeoutопределяет количество миллисекунд, разрешенных до возбужденияTimeoutError.headersопределяет HTTP-заголовки.Пример:
import std/strutils let exampleHtml = newHttpClient().getContent("http://example.com") assert "Example Domain" in exampleHtml assert "Pizza" notin exampleHtmlИсходный код Изменить proc newMultipartData(): MultipartData {.inline, ...raises: [], tags: [], forbids: [].}- Создаёт новый объект
MultipartData. Исходный код Изменить proc newMultipartData(xs: MultipartEntries): MultipartData {. ...raises: [ValueError], tags: [], forbids: [].}-
Создаёт новый объект multipart data и заполняет его записями
xsнапрямую.var data = newMultipartData({"action": "login", "format": "json"})Исходный код Изменить proc newProxy(url: string; auth = ""): Proxy {....raises: [], tags: [], forbids: [].}- Создаёт новый объект
TProxy. Исходный код Изменить proc newProxy(url: Uri; auth = ""): Proxy {....raises: [], tags: [], forbids: [].}- Создаёт новый объект
TProxy. Исходный код Изменить proc patch(client: AsyncHttpClient; url: Uri | string; body = ""; multipart: MultipartData = nil): Future[AsyncResponse] {. ...stackTrace: false.}- Подключается к хосту, указанному в URL, и выполняет запрос PATCH. Эта процедура использует значения httpClient, такие как
client.maxRedirects. Исходный код Изменить proc patch(client: HttpClient; url: Uri | string; body = ""; multipart: MultipartData = nil): Response- Исходный код Изменить
proc patchContent(client: AsyncHttpClient; url: Uri | string; body = ""; multipart: MultipartData = nil): Future[string] {. ...stackTrace: false.}- Подключается к хосту, указанному в URL, и возвращает содержимое запроса PATCH. Исходный код Изменить
proc patchContent(client: HttpClient; url: Uri | string; body = ""; multipart: MultipartData = nil): string- Исходный код Изменить
proc post(client: AsyncHttpClient; url: Uri | string; body = ""; multipart: MultipartData = nil): Future[AsyncResponse] {. ...stackTrace: false.}- Подключается к хосту, указанному в URL, и выполняет запрос POST. Эта процедура использует значения httpClient, такие как
client.maxRedirects. Исходный код Изменить proc post(client: HttpClient; url: Uri | string; body = ""; multipart: MultipartData = nil): Response- Исходный код Изменить
proc postContent(client: AsyncHttpClient; url: Uri | string; body = ""; multipart: MultipartData = nil): Future[string] {. ...stackTrace: false.}- Подключается к хосту, указанному в URL, и возвращает содержимое запроса POST. Исходный код Изменить
proc postContent(client: HttpClient; url: Uri | string; body = ""; multipart: MultipartData = nil): string- Исходный код Изменить
proc put(client: AsyncHttpClient; url: Uri | string; body = ""; multipart: MultipartData = nil): Future[AsyncResponse] {. ...stackTrace: false.}- Подключается к хосту, указанному в URL, и выполняет запрос PUT. Эта процедура использует значения httpClient, такие как
client.maxRedirects. Исходный код Изменить proc put(client: HttpClient; url: Uri | string; body = ""; multipart: MultipartData = nil): Response- Исходный код Изменить
proc putContent(client: AsyncHttpClient; url: Uri | string; body = ""; multipart: MultipartData = nil): Future[string] {. ...stackTrace: false.}- Подключается к хосту, указанному в URL, и возвращает содержимое запроса PUT. Исходный код Изменить
proc putContent(client: HttpClient; url: Uri | string; body = ""; multipart: MultipartData = nil): string- Исходный код Изменить
proc request(client: AsyncHttpClient; url: Uri | string; httpMethod: HttpMethod | string = HttpGet; body = ""; headers: HttpHeaders = nil; multipart: MultipartData = nil): Future[ AsyncResponse] {....stackTrace: false.}-
Подключается к хосту, указанному в URL, и выполняет запрос с использованием пользовательского метода, заданного строкой
httpMethod.Подключение будет поддерживаться в активном состоянии. Дополнительные запросы на тот же
clientк тому же хосту не потребуют создания нового подключения. Подключение можно закрыть с помощью процедурыclose.Эта процедура будет следовать переадресациям до максимального числа переадресаций, указанного в
client.maxRedirects.Необходимо убедиться, что
urlне содержит символов новой строки. В противном случае будет возбужденоAssertionDefect.headers— это HTTP-заголовки, которые переопределяютclient.headersтолько для этого конкретного запроса и не будут сохранены.Устарело с версии v1.5: используйте перечисление HttpMethod вместо параметра строки httpMethod, который устарел.
Исходный код Изменить proc request(client: HttpClient; url: Uri | string; httpMethod: HttpMethod | string = HttpGet; body = ""; headers: HttpHeaders = nil; multipart: MultipartData = nil): Response- Исходный код Изменить
© 2006–2024 Andreas Rumpf
Licensed under the MIT License.
https://nim-lang.org/docs/httpclient.html