Forum: Mikrocontroller und Digitale Elektronik Einfacher Webserver (ermicro), wie CSS cachen lassen?


von Georg (Gast)


Lesenswert?

Hallo zusammen,

ich habe einen einfachen Webserver nach der Vorlage von 
http://www.ermicro.com/blog/?p=1773 auf einem Atmega2560 und W5100 mit 
Atmelstudio programmiert. Der Client kann von Benutzer getätigte 
Einstellungen an den Server zurücksenden. Dieser aktualisiert darauf hin 
die Seite.

Neben der HTML Datei wird eine CSS Datei zum Client übertragen. Leider 
wird nach jeder Aktualisierung vom Browser nach der CSS Datei gefragt. 
Die CSS Datei ist relativ groß, und ihre Übertragung dauert lange. Ich 
würde daher die CSS im Browser cache belassen wollen. Die Frage ist aber 
wie, (bzw. warum der Browser nicht automatisch die CSS aus dem cache 
holt.)

Es gab hier vor langer Zeit die gleiche Frage:
Beitrag "uC gehostete webseite vom PC browser cachen lassen"
Es soll per "HTTP-Header" und per "Content type" geschehen.

Das verstehe ich aber leider nicht: Auf die client Anfragen hin
1
GET / HTTP/1.1
2
Host: 192.168.1.10
3
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0
4
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
5
Accept-Language: de,en-US;q=0.7,en;q=0.3
6
Accept-Encoding: gzip, deflate
7
Connection: keep-alive

oder
1
POST / HTTP/1.1
2
Host: 192.168.1.10
3
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0
4
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
5
Accept-Language: de,en-US;q=0.7,en;q=0.3
6
Accept-Encoding: gzip, deflate
7
Referer: http://192.168.1.10/
8
Connection: keep-alive
9
Content-Type: application/x-www-form-urlencoded
10
Content-Length: 17
11
12
L00=1&L01=1&L02=1

sende ich eine einzige HTML Datei, in der ich nach meiner Verständnis 
nur einmal den "Content type" dieser HTML-Datei angeben kann:
1
// Create the HTTP Response Header
2
strcpy_P((char *)buf,PSTR("HTTP/1.0 200 OK\r\n"));
3
strcpy_P((char *)buf,PSTR("Content-Type: text/html; charset=utf-8\r\n"));
4
strcpy_P((char *)buf,PSTR("Expires: Fri, 31 Jan 2099 06:06:06 GMT\r\n"));
5
strcpy_P((char *)buf,PSTR("Last-Modified: Di, 05 Jan 2016 11:30:00 GMT\r\n"));
6
strcpy_P((char *)buf,PSTR("\r\n"));
7
strcat_P((char *)buf,PSTR("<html>\r\n"));
8
strcat_P((char *)buf,PSTR("<head>\r\n"));
9
strcat_P((char *)buf,PSTR("<LINK rel=\"stylesheet\" h r e f=\"mystyle.css?v=1\" type=\"text/css\">\r\n"));
10
strcat_P((char *)buf,PSTR("</head>\r\n"));
11
strcat_P((char *)buf,PSTR("<body>\r\n"));
12
strcat_P((char *)buf,PSTR("<p><form method=\"POST\">\r\n"));
13
 ...

(h r e f musste ich hier so schreiben, da sonst der Posting als Spam 
deklariert wurde)
Die CSS Anfrage vom Client ist folgende:
1
GET /mystyle.css?v=1 HTTP/1.1
2
Host: 192.168.1.10
3
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0
4
Accept: text/css,*/*;q=0.1
5
Accept-Language: de,en-US;q=0.7,en;q=0.3
6
Accept-Encoding: gzip, deflate
7
Referer: http://192.168.1.10/
8
Connection: keep-alive

Darauf hin wird die CSS Datei gesendet.

Ich wäre sehr dankbar dafür, wenn mir das jemand erklären könnte.

Vielen Dank und Viele Grüße
Georg

von Christian K. (the_kirsch)


Lesenswert?

Hast du auch beim der CSS-Datei den Header Last-Modified gesetzt?
Eventuell stört das ?v=1

von Georg (Gast)


Lesenswert?

>>Hast du auch beim der CSS-Datei den Header Last-Modified gesetzt?
Genau das ist mein Problem, dass ich nicht weiß wie ich das machen kann.

Was ich bisher dazu gefunden war,
- war die Möglichkeit über eine .htaccess Datei die Expires-Zeit 
einzustellen
(https://gtmetrix.com/add-expires-headers.html)
- oder über eine "Dynamic Style Sheets"
(http://www.webmasterpro.de/coding/article/php-in-css-dss-dynamic-style-sheet.html)

Letztere habe ich versucht folgendermaßen in den CSS-Datei anzufügen, 
was nicht funktioniert hat.
1
strcpy_P((char *)buf,PSTR("<?php\r\n"));
2
strcat_P((char *)buf,PSTR("header('Content-type: text/css');\r\n"));
3
strcat_P((char *)buf,PSTR("header(\"Expires: Fri, 31 Jan 2099 06:06:06 GMT\");\r\n"));
4
strcat_P((char *)buf,PSTR("?>\r\n"));
5
...


>>Eventuell stört das ?v=1
Mit oder ohne ist das Ergebnis das Gleiche.

von Daniel A. (daniel-a)


Lesenswert?

Es gibt 4 Möglichkeiten eine Seite zu cachen.

1) Expires header:
Man sendet mit wann die seite Ablauft, das hast du bei der HTML Seite 
bereits:
1
strcpy_P((char *)buf,PSTR("Expires: Fri, 31 Jan 2099 06:06:06 GMT\r\n"));

Das muss dann nurnoch dort hinzugefügt werden, wo die css datei gesendet 
wird. 2099 ist aber doch etwas wenig.

2) Last Modified und If-Modified-Since header. Der erste wird vom server 
gesendet, der zweite vom client. Wenn last modified vor oder gleich if 
modified since ist sollte nur ein status 304 gesendet werden.

3) Etag. Von der url unabhängig. Der server sendet den Etag header mit, 
der Browser If-None-Match und bei übereinstimmung wird nur 304 gesendet.

4) Application Cache. In einer Datei werden die zu Cachenden Dateien 
angegeben. Diese sind dann selbst offline erreichbar. Aktualliserungen 
müssen mit javascript erfolgen und was mal im cache ist ist in diesem 
fall fast nichtmehr rauszukriegen.

von Christian K. (the_kirsch)


Lesenswert?

Georg schrieb:
>>>Hast du auch beim der CSS-Datei den Header Last-Modified gesetzt?
> Genau das ist mein Problem, dass ich nicht weiß wie ich das machen kann.

Aber genau das ist zwingend erforderlich, Jede einzelne Datei brauch den 
Header damit diese Datei gecached werden kann.

Du hast das jetzt nur für die Startseite gemacht, die müsste dann ach 
gecached werden. Hast du dir das mal mit Wireshark angeschaut?


Und PHP auf einem Microkontroller bringt nichts wenn da kein 
PHP-Interpreter läuft.



Zeig doch mal den Quellcode, wie hast du die CSS-Datei eingebunden

von Georg (Gast)


Lesenswert?

Vielen Dank für die Hinweise!

Das Mozilla Add-on Firebug zeigt jetzt an, dass die CSS Datei die 
gewünschte Expires Datum hat:
1
Data Size  3830
2
Expires    Sat Jan 31 2088 07:06:05 GMT+0100 (W. Europe Standard Time)
3
Fetch Count  54
4
Last Fetched  Sun Mar 06 2016 09:03:46 GMT+0100 (W. Europe Standard Time)
5
Last Modified  Sun Mar 06 2016 08:43:41 GMT+0100 (W. Europe Standard Time)

sowie
1
"Die Anfrage wurde direkt über den Cache abgewickelt, daher 
2
gibt es keine Antwort vom Server. Siehe unten für die 
3
zwischengespeicherte Antwort."



Vollständigkeitshalber ist unten der Quellcode zu finden:

1
// Check the Request Header
2
getidx=strindex((char *)buf,"GET /");
3
postidx=strindex((char *)buf,"POST /");
4
getcssidx=strindex((char *)buf,"GET /mystyle.css");
5
6
// Send CSS
7
if(getcssidx >= 0)
8
{
9
  strcpy_P((char *)buf,PSTR("HTTP/1.1 200 OK\r\n"));
10
  strcat_P((char *)buf,PSTR("Content-Type: text/css\r\n"));
11
  strcat_P((char *)buf,PSTR("Expires: Fri, 31 Jan 2088 06:06:06 GMT\r\n"));
12
  strcat_P((char *)buf,PSTR("Last-Modified: Di, 05 Jan 2016 11:30:00 GMT\r\n"));
13
  strcat_P((char *)buf,PSTR("\r\n"));
14
15
  strcat_P((char *)buf,PSTR("body {\r\n"));
16
  strcat_P((char *)buf,PSTR("background: #666;\r\n"));
17
  strcat_P((char *)buf,PSTR("}\r\n"));
18
  
19
  ...
20
  
21
  if (send(sockreg,buf,strlen((char *)buf)) <= 0) break;  
22
}
23
24
// Check client POST and send HTML
25
if ( (getidx >= 0 || postidx >= 0)   &&   (getcssidx < 0)  ) 
26
{
27
 ...

Vielen Dank nochmal für alle Beiträge.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.