V2.1
This commit is contained in:
@ -0,0 +1,7 @@
|
||||
# See: https://github.com/codespell-project/codespell#using-a-config-file
|
||||
[codespell]
|
||||
# In the event of a false positive, add the problematic word, in all lowercase, to a comma-separated list here:
|
||||
ignore-words-list = ,
|
||||
check-filenames =
|
||||
check-hidden =
|
||||
skip = ./.git,./src/utility/URLParser
|
||||
12
.pio/libdeps/esp32-s3-devkitc-1/ArduinoHttpClient/.github/dependabot.yml
vendored
Normal file
12
.pio/libdeps/esp32-s3-devkitc-1/ArduinoHttpClient/.github/dependabot.yml
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
# See: https://docs.github.com/en/github/administering-a-repository/configuration-options-for-dependency-updates#about-the-dependabotyml-file
|
||||
version: 2
|
||||
|
||||
updates:
|
||||
# Configure check for outdated GitHub Actions actions in workflows.
|
||||
# See: https://docs.github.com/en/github/administering-a-repository/keeping-your-actions-up-to-date-with-dependabot
|
||||
- package-ecosystem: github-actions
|
||||
directory: / # Check the repository's workflows under /.github/workflows/
|
||||
schedule:
|
||||
interval: daily
|
||||
labels:
|
||||
- "topic: infrastructure"
|
||||
28
.pio/libdeps/esp32-s3-devkitc-1/ArduinoHttpClient/.github/workflows/check-arduino.yml
vendored
Normal file
28
.pio/libdeps/esp32-s3-devkitc-1/ArduinoHttpClient/.github/workflows/check-arduino.yml
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
name: Check Arduino
|
||||
|
||||
# See: https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
schedule:
|
||||
# Run every Tuesday at 8 AM UTC to catch breakage caused by new rules added to Arduino Lint.
|
||||
- cron: "0 8 * * TUE"
|
||||
workflow_dispatch:
|
||||
repository_dispatch:
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Arduino Lint
|
||||
uses: arduino/arduino-lint-action@v1
|
||||
with:
|
||||
compliance: specification
|
||||
library-manager: update
|
||||
# Always use this setting for official repositories. Remove for 3rd party projects.
|
||||
official: true
|
||||
project-type: library
|
||||
63
.pio/libdeps/esp32-s3-devkitc-1/ArduinoHttpClient/.github/workflows/compile-examples.yml
vendored
Normal file
63
.pio/libdeps/esp32-s3-devkitc-1/ArduinoHttpClient/.github/workflows/compile-examples.yml
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
name: Compile Examples
|
||||
|
||||
# See: https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- ".github/workflows/compile-examples.yml"
|
||||
- "examples/**"
|
||||
- "src/**"
|
||||
pull_request:
|
||||
paths:
|
||||
- ".github/workflows/compile-examples.yml"
|
||||
- "examples/**"
|
||||
- "src/**"
|
||||
schedule:
|
||||
# Run every Tuesday at 8 AM UTC to catch breakage caused by changes to external resources (libraries, platforms).
|
||||
- cron: "0 8 * * TUE"
|
||||
workflow_dispatch:
|
||||
repository_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: ${{ matrix.board.fqbn }}
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
env:
|
||||
SKETCHES_REPORTS_PATH: sketches-reports
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
||||
matrix:
|
||||
board:
|
||||
- fqbn: arduino:samd:mkr1000
|
||||
platforms: |
|
||||
- name: arduino:samd
|
||||
artifact-name-suffix: arduino-samd-mkr1000
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Compile examples
|
||||
uses: arduino/compile-sketches@v1
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
fqbn: ${{ matrix.board.fqbn }}
|
||||
platforms: ${{ matrix.board.platforms }}
|
||||
libraries: |
|
||||
# Install the library from the local path.
|
||||
- source-path: ./
|
||||
- name: WiFi101
|
||||
sketch-paths: |
|
||||
- examples
|
||||
enable-deltas-report: true
|
||||
sketches-report-path: ${{ env.SKETCHES_REPORTS_PATH }}
|
||||
|
||||
- name: Save sketches report as workflow artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
if-no-files-found: error
|
||||
path: ${{ env.SKETCHES_REPORTS_PATH }}
|
||||
name: sketches-report-${{ matrix.board.artifact-name-suffix }}
|
||||
24
.pio/libdeps/esp32-s3-devkitc-1/ArduinoHttpClient/.github/workflows/report-size-deltas.yml
vendored
Normal file
24
.pio/libdeps/esp32-s3-devkitc-1/ArduinoHttpClient/.github/workflows/report-size-deltas.yml
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
name: Report Size Deltas
|
||||
|
||||
# See: https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- ".github/workflows/report-size-deltas.yml"
|
||||
schedule:
|
||||
# Run at the minimum interval allowed by GitHub Actions.
|
||||
# Note: GitHub Actions periodically has outages which result in workflow failures.
|
||||
# In this event, the workflows will start passing again once the service recovers.
|
||||
- cron: "*/5 * * * *"
|
||||
workflow_dispatch:
|
||||
repository_dispatch:
|
||||
|
||||
jobs:
|
||||
report:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Comment size deltas reports to PRs
|
||||
uses: arduino/report-size-deltas@v1
|
||||
with:
|
||||
# Regex matching the names of the workflow artifacts created by the "Compile Examples" workflow
|
||||
sketches-reports-source: ^sketches-report-.+
|
||||
22
.pio/libdeps/esp32-s3-devkitc-1/ArduinoHttpClient/.github/workflows/spell-check.yml
vendored
Normal file
22
.pio/libdeps/esp32-s3-devkitc-1/ArduinoHttpClient/.github/workflows/spell-check.yml
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
name: Spell Check
|
||||
|
||||
# See: https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
schedule:
|
||||
# Run every Tuesday at 8 AM UTC to catch new misspelling detections resulting from dictionary updates.
|
||||
- cron: "0 8 * * TUE"
|
||||
workflow_dispatch:
|
||||
repository_dispatch:
|
||||
|
||||
jobs:
|
||||
spellcheck:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Spell check
|
||||
uses: codespell-project/actions-codespell@master
|
||||
138
.pio/libdeps/esp32-s3-devkitc-1/ArduinoHttpClient/.github/workflows/sync-labels.yml
vendored
Normal file
138
.pio/libdeps/esp32-s3-devkitc-1/ArduinoHttpClient/.github/workflows/sync-labels.yml
vendored
Normal file
@ -0,0 +1,138 @@
|
||||
# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/sync-labels.md
|
||||
name: Sync Labels
|
||||
|
||||
# See: https://docs.github.com/en/actions/reference/events-that-trigger-workflows
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- ".github/workflows/sync-labels.ya?ml"
|
||||
- ".github/label-configuration-files/*.ya?ml"
|
||||
pull_request:
|
||||
paths:
|
||||
- ".github/workflows/sync-labels.ya?ml"
|
||||
- ".github/label-configuration-files/*.ya?ml"
|
||||
schedule:
|
||||
# Run daily at 8 AM UTC to sync with changes to shared label configurations.
|
||||
- cron: "0 8 * * *"
|
||||
workflow_dispatch:
|
||||
repository_dispatch:
|
||||
|
||||
env:
|
||||
CONFIGURATIONS_FOLDER: .github/label-configuration-files
|
||||
CONFIGURATIONS_ARTIFACT: label-configuration-files
|
||||
|
||||
jobs:
|
||||
check:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Download JSON schema for labels configuration file
|
||||
id: download-schema
|
||||
uses: carlosperate/download-file-action@v2
|
||||
with:
|
||||
file-url: https://raw.githubusercontent.com/arduino/tooling-project-assets/main/workflow-templates/assets/sync-labels/arduino-tooling-gh-label-configuration-schema.json
|
||||
location: ${{ runner.temp }}/label-configuration-schema
|
||||
|
||||
- name: Install JSON schema validator
|
||||
run: |
|
||||
sudo npm install \
|
||||
--global \
|
||||
ajv-cli \
|
||||
ajv-formats
|
||||
|
||||
- name: Validate local labels configuration
|
||||
run: |
|
||||
# See: https://github.com/ajv-validator/ajv-cli#readme
|
||||
ajv validate \
|
||||
--all-errors \
|
||||
-c ajv-formats \
|
||||
-s "${{ steps.download-schema.outputs.file-path }}" \
|
||||
-d "${{ env.CONFIGURATIONS_FOLDER }}/*.{yml,yaml}"
|
||||
|
||||
download:
|
||||
needs: check
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
filename:
|
||||
# Filenames of the shared configurations to apply to the repository in addition to the local configuration.
|
||||
# https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/sync-labels
|
||||
- universal.yml
|
||||
|
||||
steps:
|
||||
- name: Download
|
||||
uses: carlosperate/download-file-action@v2
|
||||
with:
|
||||
file-url: https://raw.githubusercontent.com/arduino/tooling-project-assets/main/workflow-templates/assets/sync-labels/${{ matrix.filename }}
|
||||
|
||||
- name: Pass configuration files to next job via workflow artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
path: |
|
||||
*.yaml
|
||||
*.yml
|
||||
if-no-files-found: error
|
||||
name: ${{ env.CONFIGURATIONS_ARTIFACT }}
|
||||
|
||||
sync:
|
||||
needs: download
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Set environment variables
|
||||
run: |
|
||||
# See: https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-environment-variable
|
||||
echo "MERGED_CONFIGURATION_PATH=${{ runner.temp }}/labels.yml" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Determine whether to dry run
|
||||
id: dry-run
|
||||
if: >
|
||||
github.event_name == 'pull_request' ||
|
||||
(
|
||||
(
|
||||
github.event_name == 'push' ||
|
||||
github.event_name == 'workflow_dispatch'
|
||||
) &&
|
||||
github.ref != format('refs/heads/{0}', github.event.repository.default_branch)
|
||||
)
|
||||
run: |
|
||||
# Use of this flag in the github-label-sync command will cause it to only check the validity of the
|
||||
# configuration.
|
||||
echo "::set-output name=flag::--dry-run"
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Download configuration files artifact
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: ${{ env.CONFIGURATIONS_ARTIFACT }}
|
||||
path: ${{ env.CONFIGURATIONS_FOLDER }}
|
||||
|
||||
- name: Remove unneeded artifact
|
||||
uses: geekyeggo/delete-artifact@v5
|
||||
with:
|
||||
name: ${{ env.CONFIGURATIONS_ARTIFACT }}
|
||||
|
||||
- name: Merge label configuration files
|
||||
run: |
|
||||
# Merge all configuration files
|
||||
shopt -s extglob
|
||||
cat "${{ env.CONFIGURATIONS_FOLDER }}"/*.@(yml|yaml) > "${{ env.MERGED_CONFIGURATION_PATH }}"
|
||||
|
||||
- name: Install github-label-sync
|
||||
run: sudo npm install --global github-label-sync
|
||||
|
||||
- name: Sync labels
|
||||
env:
|
||||
GITHUB_ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
# See: https://github.com/Financial-Times/github-label-sync
|
||||
github-label-sync \
|
||||
--labels "${{ env.MERGED_CONFIGURATION_PATH }}" \
|
||||
${{ steps.dry-run.outputs.flag }} \
|
||||
${{ github.repository }}
|
||||
@ -3,3 +3,4 @@ examples/node_test_server/node_modules/
|
||||
*.DS_Store
|
||||
*/.DS_Store
|
||||
examples/.DS_Store
|
||||
.idea/
|
||||
|
||||
@ -1 +1 @@
|
||||
{"type": "library", "name": "ArduinoHttpClient", "version": "0.4.0", "spec": {"owner": "arduino-libraries", "id": 798, "name": "ArduinoHttpClient", "requirements": null, "uri": null}}
|
||||
{"type": "library", "name": "ArduinoHttpClient", "version": "0.6.1", "spec": {"owner": "arduino-libraries", "id": 798, "name": "ArduinoHttpClient", "requirements": null, "uri": null}}
|
||||
@ -9,7 +9,7 @@
|
||||
## ArduinoHttpClient 0.3.1 - 2017.09.25
|
||||
|
||||
* Changed examples to support Arduino Create secret tabs
|
||||
* Increase WebSocket secrect-key length to 24 characters
|
||||
* Increase WebSocket secret-key length to 24 characters
|
||||
|
||||
## ArduinoHttpClient 0.3.0 - 2017.04.20
|
||||
|
||||
|
||||
@ -1,5 +1,9 @@
|
||||
# ArduinoHttpClient
|
||||
|
||||
[](https://github.com/arduino-libraries/ArduinoHttpClient/actions/workflows/check-arduino.yml)
|
||||
[](https://github.com/arduino-libraries/ArduinoHttpClient/actions/workflows/compile-examples.yml)
|
||||
[](https://github.com/arduino-libraries/ArduinoHttpClient/actions/workflows/spell-check.yml)
|
||||
|
||||
ArduinoHttpClient is a library to make it easier to interact with web servers from Arduino.
|
||||
|
||||
Derived from [Adrian McEwen's HttpClient library](https://github.com/amcewen/HttpClient)
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
#include <WiFi101.h>
|
||||
#include "arduino_secrets.h"
|
||||
///////please enter your sensitive data in the Secret tab/arduino_secrets.h
|
||||
/////// Wifi Settings ///////
|
||||
/////// WiFi Settings ///////
|
||||
char ssid[] = SECRET_SSID;
|
||||
char pass[] = SECRET_PASS;
|
||||
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
|
||||
#include "arduino_secrets.h"
|
||||
///////please enter your sensitive data in the Secret tab/arduino_secrets.h
|
||||
/////// Wifi Settings ///////
|
||||
/////// WiFi Settings ///////
|
||||
char ssid[] = SECRET_SSID;
|
||||
char pass[] = SECRET_PASS;
|
||||
|
||||
|
||||
@ -20,7 +20,7 @@
|
||||
|
||||
#include "arduino_secrets.h"
|
||||
///////please enter your sensitive data in the Secret tab/arduino_secrets.h
|
||||
/////// Wifi Settings ///////
|
||||
/////// WiFi Settings ///////
|
||||
char ssid[] = SECRET_SSID;
|
||||
char pass[] = SECRET_PASS;
|
||||
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
|
||||
#include "arduino_secrets.h"
|
||||
///////please enter your sensitive data in the Secret tab/arduino_secrets.h
|
||||
/////// Wifi Settings ///////
|
||||
/////// WiFi Settings ///////
|
||||
char ssid[] = SECRET_SSID;
|
||||
char pass[] = SECRET_PASS;
|
||||
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
The body of the PUT request looks like this:
|
||||
{"on": true} or {"on":false}
|
||||
|
||||
This example shows how to concatenate Strings to assemble the
|
||||
This example shows how to concatenate Strings to assemble the
|
||||
PUT request and the body of the request.
|
||||
|
||||
modified 15 Feb 2016
|
||||
@ -23,16 +23,16 @@
|
||||
#include "arduino_secrets.h"
|
||||
|
||||
///////please enter your sensitive data in the Secret tab/arduino_secrets.h
|
||||
/////// Wifi Settings ///////
|
||||
/////// WiFi Settings ///////
|
||||
char ssid[] = SECRET_SSID;
|
||||
char pass[] = SECRET_PASS;
|
||||
|
||||
int status = WL_IDLE_STATUS; // the Wifi radio's status
|
||||
int status = WL_IDLE_STATUS; // the WiFi radio's status
|
||||
|
||||
char hueHubIP[] = "192.168.0.3"; // IP address of the HUE bridge
|
||||
String hueUserName = "huebridgeusername"; // hue bridge username
|
||||
|
||||
// make a wifi instance and a HttpClient instance:
|
||||
// make a WiFiClient instance and a HttpClient instance:
|
||||
WiFiClient wifi;
|
||||
HttpClient httpClient = HttpClient(wifi, hueHubIP);
|
||||
|
||||
@ -42,7 +42,7 @@ void setup() {
|
||||
Serial.begin(9600);
|
||||
while (!Serial); // wait for serial port to connect.
|
||||
|
||||
// attempt to connect to Wifi network:
|
||||
// attempt to connect to WiFi network:
|
||||
while ( status != WL_CONNECTED) {
|
||||
Serial.print("Attempting to connect to WPA SSID: ");
|
||||
Serial.println(ssid);
|
||||
@ -95,4 +95,4 @@ void sendRequest(int light, String cmd, String value) {
|
||||
Serial.print("Server response: ");
|
||||
Serial.println(response);
|
||||
Serial.println();
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,29 @@
|
||||
#include "URLParser.h"
|
||||
|
||||
void setup() {
|
||||
|
||||
Serial.begin(9600);
|
||||
|
||||
while(!Serial);
|
||||
|
||||
Serial.println("starting");
|
||||
|
||||
ParsedUrl url(
|
||||
"https://www.google.com/search?q=arduino"
|
||||
);
|
||||
|
||||
Serial.print("parsed URL schema: \"");
|
||||
Serial.print(url.schema());
|
||||
Serial.print("\"\nparsed URL host: \"");
|
||||
Serial.print(url.host());
|
||||
Serial.print("\"\nparsed URL path: \"");
|
||||
Serial.print(url.path());
|
||||
Serial.print("\"\nparsed URL query: \"");
|
||||
Serial.print(url.query());
|
||||
Serial.print("\"\nparsed URL userinfo: \"");
|
||||
Serial.print(url.userinfo());
|
||||
Serial.println("\"");
|
||||
|
||||
}
|
||||
|
||||
void loop() { }
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
POST with headers client for ArduinoHttpClient library
|
||||
Connects to server once every five seconds, sends a POST request
|
||||
with custome headers and a request body
|
||||
with custom headers and a request body
|
||||
|
||||
created 14 Feb 2016
|
||||
by Tom Igoe
|
||||
@ -18,7 +18,7 @@
|
||||
#include "arduino_secrets.h"
|
||||
|
||||
///////please enter your sensitive data in the Secret tab/arduino_secrets.h
|
||||
/////// Wifi Settings ///////
|
||||
/////// WiFi Settings ///////
|
||||
char ssid[] = SECRET_SSID;
|
||||
char pass[] = SECRET_PASS;
|
||||
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
#include "arduino_secrets.h"
|
||||
|
||||
///////please enter your sensitive data in the Secret tab/arduino_secrets.h
|
||||
/////// Wifi Settings ///////
|
||||
/////// WiFi Settings ///////
|
||||
char ssid[] = SECRET_SSID;
|
||||
char pass[] = SECRET_PASS;
|
||||
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
#include "arduino_secrets.h"
|
||||
|
||||
///////please enter your sensitive data in the Secret tab/arduino_secrets.h
|
||||
/////// Wifi Settings ///////
|
||||
/////// WiFi Settings ///////
|
||||
char ssid[] = SECRET_SSID;
|
||||
char pass[] = SECRET_PASS;
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// Released under Apache License, version 2.0
|
||||
//
|
||||
// Simple example to show how to use the HttpClient library
|
||||
// Get's the web page given at http://<kHostname><kPath> and
|
||||
// Gets the web page given at http://<kHostname><kPath> and
|
||||
// outputs the content to the serial port
|
||||
|
||||
#include <SPI.h>
|
||||
@ -14,7 +14,7 @@
|
||||
#include "arduino_secrets.h"
|
||||
|
||||
///////please enter your sensitive data in the Secret tab/arduino_secrets.h
|
||||
/////// Wifi Settings ///////
|
||||
/////// WiFi Settings ///////
|
||||
char ssid[] = SECRET_SSID;
|
||||
char pass[] = SECRET_PASS;
|
||||
|
||||
@ -42,7 +42,7 @@ void setup()
|
||||
; // wait for serial port to connect. Needed for native USB port only
|
||||
}
|
||||
|
||||
// attempt to connect to Wifi network:
|
||||
// attempt to connect to WiFi network:
|
||||
Serial.print("Attempting to connect to WPA SSID: ");
|
||||
Serial.println(ssid);
|
||||
while (WiFi.begin(ssid, pass) != WL_CONNECTED) {
|
||||
@ -129,5 +129,3 @@ void loop()
|
||||
// And just stop, now that we've tried a download
|
||||
while(1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
#include "arduino_secrets.h"
|
||||
|
||||
///////please enter your sensitive data in the Secret tab/arduino_secrets.h
|
||||
/////// Wifi Settings ///////
|
||||
/////// WiFi Settings ///////
|
||||
char ssid[] = SECRET_SSID;
|
||||
char pass[] = SECRET_PASS;
|
||||
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
#include "arduino_secrets.h"
|
||||
|
||||
///////please enter your sensitive data in the Secret tab/arduino_secrets.h
|
||||
/////// Wifi Settings ///////
|
||||
/////// WiFi Settings ///////
|
||||
char ssid[] = SECRET_SSID;
|
||||
char pass[] = SECRET_PASS;
|
||||
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
#include "arduino_secrets.h"
|
||||
|
||||
///////please enter your sensitive data in the Secret tab/arduino_secrets.h
|
||||
/////// Wifi Settings ///////
|
||||
/////// WiFi Settings ///////
|
||||
char ssid[] = SECRET_SSID;
|
||||
char pass[] = SECRET_PASS;
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#######################################
|
||||
# Syntax Coloring Map For HttpClient
|
||||
# Syntax Coloring Map For ArduinoHttpClient
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
|
||||
@ -1,12 +0,0 @@
|
||||
{
|
||||
"name": "ArduinoHttpClient",
|
||||
"keywords": "http, web, client, ethernet, wifi, GSM",
|
||||
"description": "Easily interact with web servers from Arduino, using HTTP and WebSocket's.",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/arduino-libraries/ArduinoHttpClient.git"
|
||||
},
|
||||
"frameworks": "arduino",
|
||||
"platforms": "*",
|
||||
"version": "0.4.0"
|
||||
}
|
||||
@ -1,8 +1,8 @@
|
||||
name=ArduinoHttpClient
|
||||
version=0.4.0
|
||||
version=0.6.1
|
||||
author=Arduino
|
||||
maintainer=Arduino <info@arduino.cc>
|
||||
sentence=[EXPERIMENTAL] Easily interact with web servers from Arduino, using HTTP and WebSocket's.
|
||||
sentence=[EXPERIMENTAL] Easily interact with web servers from Arduino, using HTTP and WebSockets.
|
||||
paragraph=This library can be used for HTTP (GET, POST, PUT, DELETE) requests to a web server. It also supports exchanging messages with WebSocket servers. Based on Adrian McEwen's HttpClient library.
|
||||
category=Communication
|
||||
url=https://github.com/arduino-libraries/ArduinoHttpClient
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
|
||||
#include "HttpClient.h"
|
||||
#include "b64.h"
|
||||
|
||||
// Initialize constants
|
||||
const char* HttpClient::kUserAgent = "Arduino/2.2.0";
|
||||
const char* HttpClient::kContentLengthPrefix = HTTP_HEADER_CONTENT_LENGTH ": ";
|
||||
@ -39,6 +40,7 @@ void HttpClient::resetState()
|
||||
iIsChunked = false;
|
||||
iChunkLength = 0;
|
||||
iHttpResponseTimeout = kHttpResponseTimeout;
|
||||
iHttpWaitForDataDelay = kHttpWaitForDataDelay;
|
||||
}
|
||||
|
||||
void HttpClient::stop()
|
||||
@ -83,7 +85,7 @@ int HttpClient::startRequest(const char* aURLPath, const char* aHttpMethod,
|
||||
{
|
||||
if (iServerName)
|
||||
{
|
||||
if (!iClient->connect(iServerName, iServerPort) > 0)
|
||||
if (!(iClient->connect(iServerName, iServerPort) > 0))
|
||||
{
|
||||
#ifdef LOGGING
|
||||
Serial.println("Connection failed");
|
||||
@ -93,7 +95,7 @@ int HttpClient::startRequest(const char* aURLPath, const char* aHttpMethod,
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!iClient->connect(iServerAddress, iServerPort) > 0)
|
||||
if (!(iClient->connect(iServerAddress, iServerPort) > 0))
|
||||
{
|
||||
#ifdef LOGGING
|
||||
Serial.println("Connection failed");
|
||||
@ -160,7 +162,7 @@ int HttpClient::sendInitialHeaders(const char* aURLPath, const char* aHttpMethod
|
||||
{
|
||||
iClient->print("Host: ");
|
||||
iClient->print(iServerName);
|
||||
if (iServerPort != kHttpPort)
|
||||
if (iServerPort != kHttpPort && iServerPort != kHttpsPort)
|
||||
{
|
||||
iClient->print(":");
|
||||
iClient->print(iServerPort);
|
||||
@ -420,7 +422,7 @@ int HttpClient::responseStatusCode()
|
||||
{
|
||||
if (available())
|
||||
{
|
||||
c = read();
|
||||
c = HttpClient::read();
|
||||
if (c != -1)
|
||||
{
|
||||
switch(iState)
|
||||
@ -472,7 +474,7 @@ int HttpClient::responseStatusCode()
|
||||
{
|
||||
// We haven't got any data, so let's pause to allow some to
|
||||
// arrive
|
||||
delay(kHttpWaitForDataDelay);
|
||||
delay(iHttpWaitForDataDelay);
|
||||
}
|
||||
}
|
||||
if ( (c == '\n') && (iStatusCode < 200 && iStatusCode != 101) )
|
||||
@ -521,7 +523,7 @@ int HttpClient::skipResponseHeaders()
|
||||
{
|
||||
// We haven't got any data, so let's pause to allow some to
|
||||
// arrive
|
||||
delay(kHttpWaitForDataDelay);
|
||||
delay(iHttpWaitForDataDelay);
|
||||
}
|
||||
}
|
||||
if (endOfHeadersReached())
|
||||
@ -541,7 +543,7 @@ bool HttpClient::endOfHeadersReached()
|
||||
return (iState == eReadingBody || iState == eReadingChunkLength || iState == eReadingBodyChunk);
|
||||
};
|
||||
|
||||
int HttpClient::contentLength()
|
||||
long HttpClient::contentLength()
|
||||
{
|
||||
// skip the response headers, if they haven't been read already
|
||||
if (!endOfHeadersReached())
|
||||
@ -586,7 +588,7 @@ String HttpClient::responseBody()
|
||||
}
|
||||
|
||||
if (bodyLength > 0 && (unsigned int)bodyLength != response.length()) {
|
||||
// failure, we did not read in reponse content length bytes
|
||||
// failure, we did not read in response content length bytes
|
||||
return String((const char*)NULL);
|
||||
}
|
||||
|
||||
@ -684,12 +686,12 @@ int HttpClient::read()
|
||||
|
||||
bool HttpClient::headerAvailable()
|
||||
{
|
||||
// clear the currently store header line
|
||||
// clear the currently stored header line
|
||||
iHeaderLine = "";
|
||||
|
||||
while (!endOfHeadersReached())
|
||||
{
|
||||
uint64_t i =0;
|
||||
|
||||
{
|
||||
// read a byte from the header
|
||||
int c = readHeader();
|
||||
|
||||
if (c == '\r' || c == '\n')
|
||||
@ -705,13 +707,7 @@ bool HttpClient::headerAvailable()
|
||||
continue;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
|
||||
if(i > 1024*2)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// append byte to header line
|
||||
iHeaderLine += (char)c;
|
||||
}
|
||||
@ -767,7 +763,7 @@ int HttpClient::read(uint8_t *buf, size_t size)
|
||||
|
||||
int HttpClient::readHeader()
|
||||
{
|
||||
char c = read();
|
||||
char c = HttpClient::read();
|
||||
|
||||
if (endOfHeadersReached())
|
||||
{
|
||||
@ -823,7 +819,11 @@ int HttpClient::readHeader()
|
||||
case eReadingContentLength:
|
||||
if (isdigit(c))
|
||||
{
|
||||
iContentLength = iContentLength*10 + (c - '0');
|
||||
long _iContentLength = iContentLength*10 + (c - '0');
|
||||
// Only apply if the value didn't wrap around
|
||||
if (_iContentLength > iContentLength) {
|
||||
iContentLength = _iContentLength;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@ -43,6 +43,7 @@ class HttpClient : public Client
|
||||
public:
|
||||
static const int kNoContentLengthHeader =-1;
|
||||
static const int kHttpPort =80;
|
||||
static const int kHttpsPort =443;
|
||||
static const char* kUserAgent;
|
||||
|
||||
// FIXME Write longer API request, using port and user-agent, example
|
||||
@ -228,7 +229,7 @@ public:
|
||||
*/
|
||||
String readHeaderName();
|
||||
|
||||
/** Read the vallue of the current response header.
|
||||
/** Read the value of the current response header.
|
||||
Returns empty string if a header is not available.
|
||||
*/
|
||||
String readHeaderValue();
|
||||
@ -272,7 +273,7 @@ public:
|
||||
@return Length of the body, in bytes, or kNoContentLengthHeader if no
|
||||
Content-Length header was returned by the server
|
||||
*/
|
||||
int contentLength();
|
||||
long contentLength();
|
||||
|
||||
/** Returns if the response body is chunked
|
||||
@return true if response body is chunked, false otherwise
|
||||
@ -317,6 +318,8 @@ public:
|
||||
virtual operator bool() { return bool(iClient); };
|
||||
virtual uint32_t httpResponseTimeout() { return iHttpResponseTimeout; };
|
||||
virtual void setHttpResponseTimeout(uint32_t timeout) { iHttpResponseTimeout = timeout; };
|
||||
virtual uint32_t httpWaitForDataDelay() { return iHttpWaitForDataDelay; };
|
||||
virtual void setHttpWaitForDataDelay(uint32_t delay) { iHttpWaitForDataDelay = delay; };
|
||||
protected:
|
||||
/** Reset internal state data back to the "just initialised" state
|
||||
*/
|
||||
@ -340,8 +343,8 @@ protected:
|
||||
|
||||
// Number of milliseconds that we wait each time there isn't any data
|
||||
// available to be read (during status code and header processing)
|
||||
static const int kHttpWaitForDataDelay = 1000;
|
||||
// Number of milliseconds that we'll wait in total without receiveing any
|
||||
static const int kHttpWaitForDataDelay = 100;
|
||||
// Number of milliseconds that we'll wait in total without receiving any
|
||||
// data before returning HTTP_ERROR_TIMED_OUT (during status code and header
|
||||
// processing)
|
||||
static const int kHttpResponseTimeout = 30*1000;
|
||||
@ -372,7 +375,7 @@ protected:
|
||||
// Stores the status code for the response, once known
|
||||
int iStatusCode;
|
||||
// Stores the value of the Content-Length header, if present
|
||||
int iContentLength;
|
||||
long iContentLength;
|
||||
// How many bytes of the response body have been read by the user
|
||||
int iBodyLengthConsumed;
|
||||
// How far through a Content-Length header prefix we are
|
||||
@ -384,6 +387,7 @@ protected:
|
||||
// Stores the value of the current chunk length, if present
|
||||
int iChunkLength;
|
||||
uint32_t iHttpResponseTimeout;
|
||||
uint32_t iHttpWaitForDataDelay;
|
||||
bool iConnectionClose;
|
||||
bool iSendDefaultRequestHeaders;
|
||||
String iHeaderLine;
|
||||
|
||||
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* PackageLicenseDeclared: Apache-2.0
|
||||
* Copyright (c) 2017 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The following class is defined in mbed libraries, in case of STM32H7 include the original library
|
||||
*/
|
||||
#if defined __has_include
|
||||
# if __has_include(<utility/http_parsed_url.h>)
|
||||
# include <utility/http_parsed_url.h>
|
||||
# else
|
||||
# define NO_HTTP_PARSED
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef NO_HTTP_PARSED
|
||||
#ifndef _MBED_HTTP_PARSED_URL_H_
|
||||
#define _MBED_HTTP_PARSED_URL_H_
|
||||
|
||||
#include "utility/URLParser/http_parser.h"
|
||||
|
||||
class ParsedUrl {
|
||||
public:
|
||||
ParsedUrl(const char* url) {
|
||||
struct http_parser_url parsed_url;
|
||||
http_parser_parse_url(url, strlen(url), false, &parsed_url);
|
||||
|
||||
for (size_t ix = 0; ix < UF_MAX; ix++) {
|
||||
char* value;
|
||||
if (parsed_url.field_set & (1 << ix)) {
|
||||
value = (char*)calloc(parsed_url.field_data[ix].len + 1, 1);
|
||||
memcpy(value, url + parsed_url.field_data[ix].off,
|
||||
parsed_url.field_data[ix].len);
|
||||
}
|
||||
else {
|
||||
value = (char*)calloc(1, 1);
|
||||
}
|
||||
|
||||
switch ((http_parser_url_fields)ix) {
|
||||
case UF_SCHEMA: _schema = value; break;
|
||||
case UF_HOST: _host = value; break;
|
||||
case UF_PATH: _path = value; break;
|
||||
case UF_QUERY: _query = value; break;
|
||||
case UF_USERINFO: _userinfo = value; break;
|
||||
default:
|
||||
// PORT is already parsed, FRAGMENT is not relevant for HTTP requests
|
||||
free(value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_port = parsed_url.port;
|
||||
if (!_port) {
|
||||
if (strcmp(_schema, "https") == 0 || strcmp(_schema, "wss") == 0) {
|
||||
_port = 443;
|
||||
}
|
||||
else {
|
||||
_port = 80;
|
||||
}
|
||||
}
|
||||
|
||||
if (strcmp(_path, "") == 0) {
|
||||
free(_path);
|
||||
_path = (char*)calloc(2, 1);
|
||||
_path[0] = '/';
|
||||
}
|
||||
}
|
||||
|
||||
~ParsedUrl() {
|
||||
if (_schema) free(_schema);
|
||||
if (_host) free(_host);
|
||||
if (_path) free(_path);
|
||||
if (_query) free(_query);
|
||||
if (_userinfo) free(_userinfo);
|
||||
}
|
||||
|
||||
uint16_t port() const { return _port; }
|
||||
char* schema() const { return _schema; }
|
||||
char* host() const { return _host; }
|
||||
char* path() const { return _path; }
|
||||
char* query() const { return _query; }
|
||||
char* userinfo() const { return _userinfo; }
|
||||
|
||||
private:
|
||||
uint16_t _port;
|
||||
char* _schema;
|
||||
char* _host;
|
||||
char* _path;
|
||||
char* _query;
|
||||
char* _userinfo;
|
||||
};
|
||||
|
||||
#endif // _MBED_HTTP_PARSED_URL_H_
|
||||
#endif // NO_HTTP_PARSED
|
||||
#undef NO_HTTP_PARSED
|
||||
@ -8,6 +8,10 @@
|
||||
|
||||
#include "HttpClient.h"
|
||||
|
||||
#ifndef WS_TX_BUFFER_SIZE
|
||||
#define WS_TX_BUFFER_SIZE 128
|
||||
#endif
|
||||
|
||||
static const int TYPE_CONTINUATION = 0x0;
|
||||
static const int TYPE_TEXT = 0x1;
|
||||
static const int TYPE_BINARY = 0x2;
|
||||
@ -86,7 +90,7 @@ private:
|
||||
private:
|
||||
bool iTxStarted;
|
||||
uint8_t iTxMessageType;
|
||||
uint8_t iTxBuffer[128];
|
||||
uint8_t iTxBuffer[WS_TX_BUFFER_SIZE];
|
||||
uint64_t iTxSize;
|
||||
|
||||
uint8_t iRxOpCode;
|
||||
|
||||
@ -0,0 +1,23 @@
|
||||
http_parser.c is based on src/http/ngx_http_parse.c from NGINX copyright
|
||||
Igor Sysoev.
|
||||
|
||||
Additional changes are licensed under the same terms as NGINX and
|
||||
copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to
|
||||
deal in the Software without restriction, including without limitation the
|
||||
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
sell copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
IN THE SOFTWARE.
|
||||
@ -0,0 +1,5 @@
|
||||
# http_parser library
|
||||
|
||||
This code is imported from: https://github.com/arduino/ArduinoCore-mbed/tree/4.1.1/libraries/SocketWrapper/src/utility/http_parser
|
||||
|
||||
The code is shrinked in size by deleting all the unrelated code to url parse.
|
||||
@ -0,0 +1,591 @@
|
||||
#if defined __has_include
|
||||
# if ! __has_include(<utility/http_parser/http_parser.h>) && ! __has_include(<http_parser.h>)
|
||||
# define NO_HTTP_PARSER
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef NO_HTTP_PARSER
|
||||
/* Based on src/http/ngx_http_parse.c from NGINX copyright Igor Sysoev
|
||||
*
|
||||
* Additional changes are licensed under the same terms as NGINX and
|
||||
* copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
#include "http_parser.h"
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
||||
#ifndef BIT_AT
|
||||
# define BIT_AT(a, i) \
|
||||
(!!((unsigned int) (a)[(unsigned int) (i) >> 3] & \
|
||||
(1 << ((unsigned int) (i) & 7))))
|
||||
#endif
|
||||
|
||||
#define SET_ERRNO(e) \
|
||||
do { \
|
||||
parser->http_errno = (e); \
|
||||
} while(0)
|
||||
|
||||
#if HTTP_PARSER_STRICT
|
||||
# define T(v) 0
|
||||
#else
|
||||
# define T(v) v
|
||||
#endif
|
||||
|
||||
|
||||
static const uint8_t normal_url_char[32] = {
|
||||
/* 0 nul 1 soh 2 stx 3 etx 4 eot 5 enq 6 ack 7 bel */
|
||||
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0,
|
||||
/* 8 bs 9 ht 10 nl 11 vt 12 np 13 cr 14 so 15 si */
|
||||
0 | T(2) | 0 | 0 | T(16) | 0 | 0 | 0,
|
||||
/* 16 dle 17 dc1 18 dc2 19 dc3 20 dc4 21 nak 22 syn 23 etb */
|
||||
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0,
|
||||
/* 24 can 25 em 26 sub 27 esc 28 fs 29 gs 30 rs 31 us */
|
||||
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0,
|
||||
/* 32 sp 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' */
|
||||
0 | 2 | 4 | 0 | 16 | 32 | 64 | 128,
|
||||
/* 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / */
|
||||
1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
|
||||
/* 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 */
|
||||
1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
|
||||
/* 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? */
|
||||
1 | 2 | 4 | 8 | 16 | 32 | 64 | 0,
|
||||
/* 64 @ 65 A 66 B 67 C 68 D 69 E 70 F 71 G */
|
||||
1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
|
||||
/* 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 O */
|
||||
1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
|
||||
/* 80 P 81 Q 82 R 83 S 84 T 85 U 86 V 87 W */
|
||||
1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
|
||||
/* 88 X 89 Y 90 Z 91 [ 92 \ 93 ] 94 ^ 95 _ */
|
||||
1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
|
||||
/* 96 ` 97 a 98 b 99 c 100 d 101 e 102 f 103 g */
|
||||
1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
|
||||
/* 104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o */
|
||||
1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
|
||||
/* 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w */
|
||||
1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
|
||||
/* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */
|
||||
1 | 2 | 4 | 8 | 16 | 32 | 64 | 0, };
|
||||
|
||||
#undef T
|
||||
|
||||
enum state
|
||||
{ s_dead = 1 /* important that this is > 0 */
|
||||
|
||||
, s_start_req
|
||||
|
||||
, s_req_spaces_before_url
|
||||
, s_req_schema
|
||||
, s_req_schema_slash
|
||||
, s_req_schema_slash_slash
|
||||
, s_req_server_start
|
||||
, s_req_server
|
||||
, s_req_server_with_at
|
||||
, s_req_path
|
||||
, s_req_query_string_start
|
||||
, s_req_query_string
|
||||
, s_req_fragment_start
|
||||
, s_req_fragment
|
||||
, s_headers_done
|
||||
};
|
||||
|
||||
enum http_host_state
|
||||
{
|
||||
s_http_host_dead = 1
|
||||
, s_http_userinfo_start
|
||||
, s_http_userinfo
|
||||
, s_http_host_start
|
||||
, s_http_host_v6_start
|
||||
, s_http_host
|
||||
, s_http_host_v6
|
||||
, s_http_host_v6_end
|
||||
, s_http_host_v6_zone_start
|
||||
, s_http_host_v6_zone
|
||||
, s_http_host_port_start
|
||||
, s_http_host_port
|
||||
};
|
||||
|
||||
/* Macros for character classes; depends on strict-mode */
|
||||
#define LOWER(c) (unsigned char)(c | 0x20)
|
||||
#define IS_ALPHA(c) (LOWER(c) >= 'a' && LOWER(c) <= 'z')
|
||||
#define IS_NUM(c) ((c) >= '0' && (c) <= '9')
|
||||
#define IS_ALPHANUM(c) (IS_ALPHA(c) || IS_NUM(c))
|
||||
#define IS_HEX(c) (IS_NUM(c) || (LOWER(c) >= 'a' && LOWER(c) <= 'f'))
|
||||
#define IS_MARK(c) ((c) == '-' || (c) == '_' || (c) == '.' || \
|
||||
(c) == '!' || (c) == '~' || (c) == '*' || (c) == '\'' || (c) == '(' || \
|
||||
(c) == ')')
|
||||
#define IS_USERINFO_CHAR(c) (IS_ALPHANUM(c) || IS_MARK(c) || (c) == '%' || \
|
||||
(c) == ';' || (c) == ':' || (c) == '&' || (c) == '=' || (c) == '+' || \
|
||||
(c) == '$' || (c) == ',')
|
||||
|
||||
#if HTTP_PARSER_STRICT
|
||||
#define IS_URL_CHAR(c) (BIT_AT(normal_url_char, (unsigned char)c))
|
||||
#define IS_HOST_CHAR(c) (IS_ALPHANUM(c) || (c) == '.' || (c) == '-')
|
||||
#else
|
||||
#define IS_URL_CHAR(c) \
|
||||
(BIT_AT(normal_url_char, (unsigned char)c) || ((c) & 0x80))
|
||||
#define IS_HOST_CHAR(c) \
|
||||
(IS_ALPHANUM(c) || (c) == '.' || (c) == '-' || (c) == '_')
|
||||
#endif
|
||||
|
||||
/* Our URL parser.
|
||||
*
|
||||
* This is designed to be shared by http_parser_execute() for URL validation,
|
||||
* hence it has a state transition + byte-for-byte interface. In addition, it
|
||||
* is meant to be embedded in http_parser_parse_url(), which does the dirty
|
||||
* work of turning state transitions URL components for its API.
|
||||
*
|
||||
* This function should only be invoked with non-space characters. It is
|
||||
* assumed that the caller cares about (and can detect) the transition between
|
||||
* URL and non-URL states by looking for these.
|
||||
*/
|
||||
static enum state
|
||||
parse_url_char(enum state s, const char ch)
|
||||
{
|
||||
if (ch == ' ' || ch == '\r' || ch == '\n') {
|
||||
return s_dead;
|
||||
}
|
||||
|
||||
#if HTTP_PARSER_STRICT
|
||||
if (ch == '\t' || ch == '\f') {
|
||||
return s_dead;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (s) {
|
||||
case s_req_spaces_before_url:
|
||||
/* Proxied requests are followed by scheme of an absolute URI (alpha).
|
||||
* All methods except CONNECT are followed by '/' or '*'.
|
||||
*/
|
||||
|
||||
if (ch == '/' || ch == '*') {
|
||||
return s_req_path;
|
||||
}
|
||||
|
||||
if (IS_ALPHA(ch)) {
|
||||
return s_req_schema;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case s_req_schema:
|
||||
if (IS_ALPHA(ch)) {
|
||||
return s;
|
||||
}
|
||||
|
||||
if (ch == ':') {
|
||||
return s_req_schema_slash;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case s_req_schema_slash:
|
||||
if (ch == '/') {
|
||||
return s_req_schema_slash_slash;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case s_req_schema_slash_slash:
|
||||
if (ch == '/') {
|
||||
return s_req_server_start;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case s_req_server_with_at:
|
||||
if (ch == '@') {
|
||||
return s_dead;
|
||||
}
|
||||
|
||||
/* FALLTHROUGH */
|
||||
case s_req_server_start:
|
||||
case s_req_server:
|
||||
if (ch == '/') {
|
||||
return s_req_path;
|
||||
}
|
||||
|
||||
if (ch == '?') {
|
||||
return s_req_query_string_start;
|
||||
}
|
||||
|
||||
if (ch == '@') {
|
||||
return s_req_server_with_at;
|
||||
}
|
||||
|
||||
if (IS_USERINFO_CHAR(ch) || ch == '[' || ch == ']') {
|
||||
return s_req_server;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case s_req_path:
|
||||
if (IS_URL_CHAR(ch)) {
|
||||
return s;
|
||||
}
|
||||
|
||||
switch (ch) {
|
||||
case '?':
|
||||
return s_req_query_string_start;
|
||||
|
||||
case '#':
|
||||
return s_req_fragment_start;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case s_req_query_string_start:
|
||||
case s_req_query_string:
|
||||
if (IS_URL_CHAR(ch)) {
|
||||
return s_req_query_string;
|
||||
}
|
||||
|
||||
switch (ch) {
|
||||
case '?':
|
||||
/* allow extra '?' in query string */
|
||||
return s_req_query_string;
|
||||
|
||||
case '#':
|
||||
return s_req_fragment_start;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case s_req_fragment_start:
|
||||
if (IS_URL_CHAR(ch)) {
|
||||
return s_req_fragment;
|
||||
}
|
||||
|
||||
switch (ch) {
|
||||
case '?':
|
||||
return s_req_fragment;
|
||||
|
||||
case '#':
|
||||
return s;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case s_req_fragment:
|
||||
if (IS_URL_CHAR(ch)) {
|
||||
return s;
|
||||
}
|
||||
|
||||
switch (ch) {
|
||||
case '?':
|
||||
case '#':
|
||||
return s;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* We should never fall out of the switch above unless there's an error */
|
||||
return s_dead;
|
||||
}
|
||||
|
||||
static enum http_host_state
|
||||
http_parse_host_char(enum http_host_state s, const char ch) {
|
||||
switch(s) {
|
||||
case s_http_userinfo:
|
||||
case s_http_userinfo_start:
|
||||
if (ch == '@') {
|
||||
return s_http_host_start;
|
||||
}
|
||||
|
||||
if (IS_USERINFO_CHAR(ch)) {
|
||||
return s_http_userinfo;
|
||||
}
|
||||
break;
|
||||
|
||||
case s_http_host_start:
|
||||
if (ch == '[') {
|
||||
return s_http_host_v6_start;
|
||||
}
|
||||
|
||||
if (IS_HOST_CHAR(ch)) {
|
||||
return s_http_host;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case s_http_host:
|
||||
if (IS_HOST_CHAR(ch)) {
|
||||
return s_http_host;
|
||||
}
|
||||
|
||||
/* FALLTHROUGH */
|
||||
case s_http_host_v6_end:
|
||||
if (ch == ':') {
|
||||
return s_http_host_port_start;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case s_http_host_v6:
|
||||
if (ch == ']') {
|
||||
return s_http_host_v6_end;
|
||||
}
|
||||
|
||||
/* FALLTHROUGH */
|
||||
case s_http_host_v6_start:
|
||||
if (IS_HEX(ch) || ch == ':' || ch == '.') {
|
||||
return s_http_host_v6;
|
||||
}
|
||||
|
||||
if (s == s_http_host_v6 && ch == '%') {
|
||||
return s_http_host_v6_zone_start;
|
||||
}
|
||||
break;
|
||||
|
||||
case s_http_host_v6_zone:
|
||||
if (ch == ']') {
|
||||
return s_http_host_v6_end;
|
||||
}
|
||||
|
||||
/* FALLTHROUGH */
|
||||
case s_http_host_v6_zone_start:
|
||||
/* RFC 6874 Zone ID consists of 1*( unreserved / pct-encoded) */
|
||||
if (IS_ALPHANUM(ch) || ch == '%' || ch == '.' || ch == '-' || ch == '_' ||
|
||||
ch == '~') {
|
||||
return s_http_host_v6_zone;
|
||||
}
|
||||
break;
|
||||
|
||||
case s_http_host_port:
|
||||
case s_http_host_port_start:
|
||||
if (IS_NUM(ch)) {
|
||||
return s_http_host_port;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return s_http_host_dead;
|
||||
}
|
||||
|
||||
static int
|
||||
http_parse_host(const char * buf, struct http_parser_url *u, int found_at) {
|
||||
enum http_host_state s;
|
||||
|
||||
const char *p;
|
||||
uint32_t buflen = u->field_data[UF_HOST].off + u->field_data[UF_HOST].len;
|
||||
|
||||
assert(u->field_set & (1 << UF_HOST));
|
||||
|
||||
u->field_data[UF_HOST].len = 0;
|
||||
|
||||
s = found_at ? s_http_userinfo_start : s_http_host_start;
|
||||
|
||||
for (p = buf + u->field_data[UF_HOST].off; p < buf + buflen; p++) {
|
||||
enum http_host_state new_s = http_parse_host_char(s, *p);
|
||||
|
||||
if (new_s == s_http_host_dead) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch(new_s) {
|
||||
case s_http_host:
|
||||
if (s != s_http_host) {
|
||||
u->field_data[UF_HOST].off = p - buf;
|
||||
}
|
||||
u->field_data[UF_HOST].len++;
|
||||
break;
|
||||
|
||||
case s_http_host_v6:
|
||||
if (s != s_http_host_v6) {
|
||||
u->field_data[UF_HOST].off = p - buf;
|
||||
}
|
||||
u->field_data[UF_HOST].len++;
|
||||
break;
|
||||
|
||||
case s_http_host_v6_zone_start:
|
||||
case s_http_host_v6_zone:
|
||||
u->field_data[UF_HOST].len++;
|
||||
break;
|
||||
|
||||
case s_http_host_port:
|
||||
if (s != s_http_host_port) {
|
||||
u->field_data[UF_PORT].off = p - buf;
|
||||
u->field_data[UF_PORT].len = 0;
|
||||
u->field_set |= (1 << UF_PORT);
|
||||
}
|
||||
u->field_data[UF_PORT].len++;
|
||||
break;
|
||||
|
||||
case s_http_userinfo:
|
||||
if (s != s_http_userinfo) {
|
||||
u->field_data[UF_USERINFO].off = p - buf ;
|
||||
u->field_data[UF_USERINFO].len = 0;
|
||||
u->field_set |= (1 << UF_USERINFO);
|
||||
}
|
||||
u->field_data[UF_USERINFO].len++;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
s = new_s;
|
||||
}
|
||||
|
||||
/* Make sure we don't end somewhere unexpected */
|
||||
switch (s) {
|
||||
case s_http_host_start:
|
||||
case s_http_host_v6_start:
|
||||
case s_http_host_v6:
|
||||
case s_http_host_v6_zone_start:
|
||||
case s_http_host_v6_zone:
|
||||
case s_http_host_port_start:
|
||||
case s_http_userinfo:
|
||||
case s_http_userinfo_start:
|
||||
return 1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
http_parser_url_init(struct http_parser_url *u) {
|
||||
memset(u, 0, sizeof(*u));
|
||||
}
|
||||
|
||||
int
|
||||
http_parser_parse_url(const char *buf, uint32_t buflen, int is_connect,
|
||||
struct http_parser_url *u)
|
||||
{
|
||||
enum state s;
|
||||
const char *p;
|
||||
enum http_parser_url_fields uf, old_uf;
|
||||
int found_at = 0;
|
||||
|
||||
u->port = u->field_set = 0;
|
||||
s = is_connect ? s_req_server_start : s_req_spaces_before_url;
|
||||
old_uf = UF_MAX;
|
||||
|
||||
for (p = buf; p < buf + buflen; p++) {
|
||||
s = parse_url_char(s, *p);
|
||||
|
||||
/* Figure out the next field that we're operating on */
|
||||
switch (s) {
|
||||
case s_dead:
|
||||
return 1;
|
||||
|
||||
/* Skip delimeters */
|
||||
case s_req_schema_slash:
|
||||
case s_req_schema_slash_slash:
|
||||
case s_req_server_start:
|
||||
case s_req_query_string_start:
|
||||
case s_req_fragment_start:
|
||||
continue;
|
||||
|
||||
case s_req_schema:
|
||||
uf = UF_SCHEMA;
|
||||
break;
|
||||
|
||||
case s_req_server_with_at:
|
||||
found_at = 1;
|
||||
|
||||
/* FALLTROUGH */
|
||||
case s_req_server:
|
||||
uf = UF_HOST;
|
||||
break;
|
||||
|
||||
case s_req_path:
|
||||
uf = UF_PATH;
|
||||
break;
|
||||
|
||||
case s_req_query_string:
|
||||
uf = UF_QUERY;
|
||||
break;
|
||||
|
||||
case s_req_fragment:
|
||||
uf = UF_FRAGMENT;
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(!"Unexpected state");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Nothing's changed; soldier on */
|
||||
if (uf == old_uf) {
|
||||
u->field_data[uf].len++;
|
||||
continue;
|
||||
}
|
||||
|
||||
u->field_data[uf].off = p - buf;
|
||||
u->field_data[uf].len = 1;
|
||||
|
||||
u->field_set |= (1 << uf);
|
||||
old_uf = uf;
|
||||
}
|
||||
|
||||
/* host must be present if there is a schema */
|
||||
/* parsing http:///toto will fail */
|
||||
if ((u->field_set & (1 << UF_SCHEMA)) &&
|
||||
(u->field_set & (1 << UF_HOST)) == 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (u->field_set & (1 << UF_HOST)) {
|
||||
if (http_parse_host(buf, u, found_at) != 0) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* CONNECT requests can only contain "hostname:port" */
|
||||
if (is_connect && u->field_set != ((1 << UF_HOST)|(1 << UF_PORT))) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (u->field_set & (1 << UF_PORT)) {
|
||||
/* Don't bother with endp; we've already validated the string */
|
||||
unsigned long v = strtoul(buf + u->field_data[UF_PORT].off, NULL, 10);
|
||||
|
||||
/* Ports have a max value of 2^16 */
|
||||
if (v > 0xffff) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
u->port = (uint16_t) v;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned long
|
||||
http_parser_version(void) {
|
||||
return HTTP_PARSER_VERSION_MAJOR * 0x10000 |
|
||||
HTTP_PARSER_VERSION_MINOR * 0x00100 |
|
||||
HTTP_PARSER_VERSION_PATCH * 0x00001;
|
||||
}
|
||||
|
||||
#endif // NO_HTTP_PARSER
|
||||
@ -0,0 +1,96 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef http_parser_h
|
||||
#define http_parser_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Also update SONAME in the Makefile whenever you change these. */
|
||||
#define HTTP_PARSER_VERSION_MAJOR 2
|
||||
#define HTTP_PARSER_VERSION_MINOR 7
|
||||
#define HTTP_PARSER_VERSION_PATCH 1
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* Compile with -DHTTP_PARSER_STRICT=0 to make less checks, but run
|
||||
* faster
|
||||
*/
|
||||
#ifndef HTTP_PARSER_STRICT
|
||||
# define HTTP_PARSER_STRICT 1
|
||||
#endif
|
||||
|
||||
|
||||
enum http_parser_url_fields
|
||||
{ UF_SCHEMA = 0
|
||||
, UF_HOST = 1
|
||||
, UF_PORT = 2
|
||||
, UF_PATH = 3
|
||||
, UF_QUERY = 4
|
||||
, UF_FRAGMENT = 5
|
||||
, UF_USERINFO = 6
|
||||
, UF_MAX = 7
|
||||
};
|
||||
|
||||
|
||||
/* Result structure for http_parser_parse_url().
|
||||
*
|
||||
* Callers should index into field_data[] with UF_* values iff field_set
|
||||
* has the relevant (1 << UF_*) bit set. As a courtesy to clients (and
|
||||
* because we probably have padding left over), we convert any port to
|
||||
* a uint16_t.
|
||||
*/
|
||||
struct http_parser_url {
|
||||
uint16_t field_set; /* Bitmask of (1 << UF_*) values */
|
||||
uint16_t port; /* Converted UF_PORT string */
|
||||
|
||||
struct {
|
||||
uint16_t off; /* Offset into buffer in which field starts */
|
||||
uint16_t len; /* Length of run in buffer */
|
||||
} field_data[UF_MAX];
|
||||
};
|
||||
|
||||
|
||||
/* Returns the library version. Bits 16-23 contain the major version number,
|
||||
* bits 8-15 the minor version number and bits 0-7 the patch level.
|
||||
* Usage example:
|
||||
*
|
||||
* unsigned long version = http_parser_version();
|
||||
* unsigned major = (version >> 16) & 255;
|
||||
* unsigned minor = (version >> 8) & 255;
|
||||
* unsigned patch = version & 255;
|
||||
* printf("http_parser v%u.%u.%u\n", major, minor, patch);
|
||||
*/
|
||||
unsigned long http_parser_version(void);
|
||||
|
||||
/* Initialize all http_parser_url members to 0 */
|
||||
void http_parser_url_init(struct http_parser_url *u);
|
||||
|
||||
/* Parse a URL; return nonzero on failure */
|
||||
int http_parser_parse_url(const char *buf, uint32_t buflen,
|
||||
int is_connect,
|
||||
struct http_parser_url *u);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
Reference in New Issue
Block a user