- Sat Jun 04, 2016 5:27 am
#48553
Hi, all,
I just tried the "2-step" proxying using a cache on SPIFFS, but to my surprise, I'm encountering the same weird "truncated page" issue.
Here is the code I'm using now:
Code: Select all#include <ESP8266WiFi.h>
#include <FS.h>
const char* ssid = "********";
const char* password = "********";
WiFiServer localServer(80);
const char* remoteHost = "www.nytimes.com";
long cacheTime;
#define CACHE_TTL 1*60*1000 // 1 minute
uint8_t buffer[1024];
void setup() {
Serial.begin(115200);
delay(10);
Serial.println();
Serial.print("Initializing Wi-Fi");
// Connect to WiFi network
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println(" Done.");
// Start the server
localServer.begin();
Serial.println("Initializing SPIFFS cache...");
if (!SPIFFS.begin()) {
Serial.println("SPIFFS init failed");
}
Dir dir = SPIFFS.openDir("/cache");
while (dir.next()) {
Serial.println("Deleting " + dir.fileName() + " from cache...");
SPIFFS.remove(String("/cache") + dir.fileName());
}
cacheTime = 0;
Serial.print("Ready. Please direct your browser to: http://");
Serial.println(WiFi.localIP());
}
void loop() {
// Check if a client browser has connected
WiFiClient browserClient = localServer.available();
if (!browserClient) {
return;
}
// Wait until the client browser sends some data
Serial.println("Serving request");
while(!browserClient.available()){
delay(1);
}
// Read the first line of the request (and ignore it)
String request = browserClient.readStringUntil('\r');
Serial.println("Request is " + request);
browserClient.flush();
// Test if we can use the cache
long now = millis();
if ( cacheTime == 0 /* no cache */
|| cacheTime > now /* millis() wrapped around */
|| now - cacheTime > CACHE_TTL /* cache is outdated */) {
Serial.println("Filling up cache");
// Connect to the real server
WiFiClient client;
Serial.println("Connecting to remote server");
if (!client.connect(remoteHost, 80)) {
// Error connecting to real server
Serial.println("Error contacting remote server");
return;
}
Serial.println("connected");
// Make a HTTP request:
client.println(String("GET / HTTP/1.1\r\n") +
"Host: " + remoteHost + "\r\n" +
"Connection: close\r\n\r\n");
Serial.println("Request sent");
// Wait for response
while(!client.available()){
delay(1);
}
Serial.println("Client available");
// Prepare cache file
File cache = SPIFFS.open(String("/cache/") + remoteHost, "w");
if (!cache) {
Serial.println("Could not create cache file");
}
while (client.available()) {
int bytesRead = client.readBytes(buffer, sizeof(buffer));
cache.write(buffer, bytesRead);
Serial.print(bytesRead);
Serial.println(" bytes downloaded to cache");
}
cache.close();
cacheTime = now;
}
// And return cached value to the browser
// Open cache file for reading
File cache = SPIFFS.open(String("/cache/") + remoteHost, "r");
if (!cache) {
Serial.println("Could not open cache file");
}
// Read it and stream it back
while (cache.available()) {
int bytesRead = cache.read((uint8_t *)buffer, sizeof(buffer));
browserClient.write((uint8_t *)buffer, bytesRead);
Serial.print(bytesRead);
Serial.println(" bytes returned to browser from cache");
}
cache.close();
Serial.println();
Serial.println("Response sent");
}
And here is the log:
Code: Select allInitializing Wi-Fi............. Done.
Initializing SPIFFS cache...
Ready. Please direct your browser to: http://192.168.0.18
Serving request
Request is GET / HTTP/1.1
Filling up cache
Connecting to remote server
connected
Request sent
Client available
1024 bytes downloaded to cache
1024 bytes downloaded to cache
1024 bytes downloaded to cache
1024 bytes downloaded to cache
1024 bytes downloaded to cache
720 bytes downloaded to cache
1024 bytes returned to browser from cache
1024 bytes returned to browser from cache
1024 bytes returned to browser from cache
1024 bytes returned to browser from cache
1024 bytes returned to browser from cache
720 bytes returned to browser from cache
Response sent
As you can see, I'm again getting that 5x1024+720 bytes truncated response instead of the full 100k+ page.
Note that writing that, I'm just realizing that (5x1024+720)/4 = 1460 , so we stop after exactly 4 ethernet frames...
I first thought about a potential timeout due to the time it takes to return these data to the browser client (first implementation) or to write it to flash (this implementation), but it wouldn't explain why writing to serial (which is much slower) works.
So maybe it's the contrary: we drain the queue of incoming messages so fast that the client.available() becomes false for a short time and then we exit the loop prematurely.
But that wouldn't explain why Serial + browser forwarding failed... Really strange.
I will test some more with delays to see how it behaves...
Apart from that, the cache logic seems to work pretty well, as subsequent calls within the same minute successfully hit the cached copy.
Kind regards,
Vicne