ESP8266 Arduino CoreでGETアクセス。HTTP/HTTPS＆プロクシを使ったHTTP通信

# はじめに
Arduino IDEでESP8266の開発を行うときに使うライブラリESP8266 Arduino Coreには、HTTP通信にかぎらず便利な機能が用意されていますが、HTTPSとプロクシを使った場合のサンプルが見つかりにくく、まとめて書いてあるページも無かったので、ここに記します。
※2020/05/31 HTTPS通信に関して、情報が古くなっていましたので、書き換えました。

## HTTP通信
暗号化されていない通信の場合

```c:http.ino
#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>

const char* ssid     = "____your SSID____";
const char* password = "____your PASSWORD____";

void setup() {
	Serial.begin(115200);
	delay(10);

	Serial.print("Connecting to ");
	Serial.println(ssid);

	WiFi.begin(ssid, password);

	while (WiFi.status() != WL_CONNECTED) {
		delay(500);
		Serial.print(".");
	}
	
	Serial.println("");
	Serial.println("WiFi connected");	
	Serial.println("IP address: ");
	Serial.println(WiFi.localIP());
}

bool Http_Get_access(String host, String url, String argument){
	WiFiClient client;
	client.setTimeout(500);

	const int httpPort = 80;
	const char* host2 = host.c_str();
	if (!client.connect(host2, httpPort)) {
		Serial.println("connection failed");
		return false;
	}
	client.print(String("GET ") + url + "?" + argument + " HTTP/1.1\r\n" +
						"Host: " + host + "\r\n" + 
						"User-Agent: ESP8266/1.0\r\n" + 
						"Connection: close\r\n\r\n");
	unsigned long timeout = micros();
	while (client.available() == 0) {
		if ( micros() - timeout  > 5000000) {
			Serial.println(">>> Client Timeout !");
			client.stop();
			return false;
		}
	}
	while(client.available()){
		String line = client.readStringUntil('\r');
		Serial.print(line);
	}
	return true;
}

void loop() {

	String host = "hoge.co.jp";
	String url = "/hoge/hoge.php";
	String argument = "key=hoge&key2=hogehoge";

	Http_Get_access( host, url, argument);

	while(1){
		delay(5000);
	}
}
```
## HTTPS通信（core2.5.0以降）
3年前に書いたHTTPS通信の関数は動かなくなっていました。いろいろ調べると

```c:
client.setFingerprint(fingerprint);
```
を使用し、WEBブラウザから証明書のSHA1のフィンガープリントを入れると書いてあるのですが、組み込み用途で使用期限が決まっている証明書を使いたくありません。調べると[ここ](https://www.motohasi.net/blog/?p=3885)にフィンガープリントを使用しない方法が書いてありましたので、関数を書き換えました。

```c:
bool Https_Get_access(String host, String url, String argument){
    BearSSL::WiFiClientSecure client;
    client.setTimeout(500);
    client.setInsecure();

    const int httpPort = 443;
    const char* host2 = host.c_str();
    if (!client.connect(host2, httpPort)) {
        Serial.println("connection failed");
        return false;
    }
    client.print(String("GET ") + url + "?" + argument + " HTTP/1.1\r\n" +
                        "Host: " + host + "\r\n" + 
                        "User-Agent: ESP8266/1.0\r\n" + 
                        "Connection: close\r\n\r\n");
    unsigned long timeout = micros();
    while (client.available() == 0) {
        if ( micros() - timeout  > 5000000) {
            Serial.println(">>> Client Timeout !");
            client.stop();
            return false;
        }
    }
    while(client.available()){
        String line = client.readStringUntil('\r');
        Serial.print(line);
    }
    return true;
}
```

## HTTPS通信（古いため動きません）
暗号化された通信の場合。関数以外は一緒なので、関数のみ記します。ちなみに、Arduino Core2.3.0だと、TLS 1.0/1.1を無効化されたサーバーにはアクセスが拒否されますので、Coreのバージョンを上げましょう。

```c:
bool Https_Get_access(String host, String url, String argument){
	WiFiClientSecure client;
	client.setTimeout(500);

	const int httpPort = 443;
	const char* host2 = host.c_str();
	if (!client.connect(host2, httpPort)) {
		Serial.println("connection failed");
		return false;
	}
	client.print(String("GET ") + url + "?" + argument + " HTTP/1.1\r\n" +
						"Host: " + host + "\r\n" + 
						"User-Agent: ESP8266/1.0\r\n" + 
						"Connection: close\r\n\r\n");
	unsigned long timeout = micros();
	while (client.available() == 0) {
		if ( micros() - timeout  > 5000000) {
			Serial.println(">>> Client Timeout !");
			client.stop();
			return false;
		}
	}
	while(client.available()){
		String line = client.readStringUntil('\r');
		Serial.print(line);
	}
	return true;
}
```

## プロクシを通したHTTP通信
プロクシをHOSTで指定した場合とIPで指定した場合の2種類の関数です。関数とloop()内だけを記します。

```c:
bool Http_Get_access_Proxy(String host, String url, String argument, String Proxy_host, int Proxy_Port){
	WiFiClient client;
	client.setTimeout(500);

	const char* host2 = Proxy_host.c_str();
	if (!client.connect(host2, Proxy_Port)) {
		Serial.println("connection failed");
		return false;
	}
	client.print(String("GET http://") + host + url + "?" + argument + " HTTP/1.1\r\n" +
						"Host: " + host + "\r\n" + 
						"User-Agent: ESP8266/1.0\r\n" + 
						"Connection: close\r\n\r\n");
	unsigned long timeout = micros();
	while (client.available() == 0) {
		if ( micros() - timeout  > 5000000) {
			Serial.println(">>> Client Timeout !");
			client.stop();
			return false;
		}
	}
	while(client.available()){
		String line = client.readStringUntil('\r');
		Serial.print(line);
	}
	return true;
}

bool Http_Get_access_Proxy(String host, String url, String argument, byte proxy_ip[], int Proxy_Port){
	WiFiClient client;
	if (!client.connect(proxy_ip, Proxy_Port)) {
		Serial.println("connection failed");
		return false;
	}
	client.print(String("GET http://") + host + url + "?" + argument + " HTTP/1.1\r\n" +
					"Host: " + host + "\r\n" +
					"User-Agent: ESP8266/1.0\r\n" +
					"Connection: close\r\n\r\n");
	unsigned long timeout = micros();
	while (client.available() == 0) {
		if ( micros() - timeout > 5000000) {
			Serial.println(">>> Client Timeout !");
			client.stop();
			return false;
		}
	}
	while(client.available()){
		String line = client.readStringUntil('\r');
		Serial.print(line);
	}
	return true;
}
void loop() {

	String host = "hoge.co.jp/";
	String url = "/hoge/hoge.php";
	String argument = "key=hoge&key2=hogehoge";
	int Proxy_Port = 8080;

	String Proxy_host = "hogeproxy.jp";
	Http_Get_access_Proxy(host, url, argument, Proxy_host , Proxy_Port);

	byte proxy_ip[] = { 192, 168, 10, 2 };
	Http_Get_access_Proxy(host, url, argument ,proxy_ip , Proxy_Port);

	while(1){
		delay(5000);
	}
}
```

## 最後に
プロクシの使ったHTTPS通信の方法が分からず、試行錯誤したのですが、うまくいきませんでした。どなたか分かる方、教えてください。