Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Enhance althttpd to support Range: attributes in the HTTP request header. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
1d3579379c47c51384b29e84d434d61d |
User & Date: | drh 2020-03-15 18:17:43.463 |
Context
2020-03-16
| ||
15:07 | Performance improvement on CGI handling in althttpd.c (check-in: 1ec2d586fc user: drh tags: trunk) | |
2020-03-15
| ||
18:17 | Enhance althttpd to support Range: attributes in the HTTP request header. (check-in: 1d3579379c user: drh tags: trunk) | |
2020-03-06
| ||
00:13 | Update the NOCASE documentation to make it clear that it uses sqlite3_strnicmp() for comparison and thus stops at the first embedded zero character in the string. (check-in: e751b0c91a user: drh tags: trunk) | |
Changes
Changes to misc/althttpd.c.
︙ | ︙ | |||
316 317 318 319 320 321 322 323 324 325 326 327 328 329 | static int ipv6Only = 0; /* Use IPv6 only */ static int ipv4Only = 0; /* Use IPv4 only */ static struct rusage priorSelf; /* Previously report SELF time */ static struct rusage priorChild; /* Previously report CHILD time */ static int mxAge = 120; /* Cache-control max-age */ static char *default_path = "/bin:/usr/bin"; /* Default PATH variable */ static char *zScgi = 0; /* Value of the SCGI env variable */ /* ** Mapping between CGI variable names and values stored in ** global variables. */ static struct { char *zEnvName; | > > | 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 | static int ipv6Only = 0; /* Use IPv6 only */ static int ipv4Only = 0; /* Use IPv4 only */ static struct rusage priorSelf; /* Previously report SELF time */ static struct rusage priorChild; /* Previously report CHILD time */ static int mxAge = 120; /* Cache-control max-age */ static char *default_path = "/bin:/usr/bin"; /* Default PATH variable */ static char *zScgi = 0; /* Value of the SCGI env variable */ static int rangeStart = 0; /* Start of a Range: request */ static int rangeEnd = 0; /* End of a Range: request */ /* ** Mapping between CGI variable names and values stored in ** global variables. */ static struct { char *zEnvName; |
︙ | ︙ | |||
1282 1283 1284 1285 1286 1287 1288 | nOut += printf("\r\n"); fflush(stdout); MakeLogEntry(0, 470); /* LOG: ETag Cache Hit */ return 1; } in = fopen(zFile,"rb"); if( in==0 ) NotFound(480); /* LOG: fopen() failed for static content */ | > > > > > > > > > | > > | > > | > | 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 | nOut += printf("\r\n"); fflush(stdout); MakeLogEntry(0, 470); /* LOG: ETag Cache Hit */ return 1; } in = fopen(zFile,"rb"); if( in==0 ) NotFound(480); /* LOG: fopen() failed for static content */ if( rangeEnd>0 && rangeStart<pStat->st_size ){ StartResponse("206 Partial Content"); if( rangeEnd>=pStat->st_size ){ rangeEnd = pStat->st_size-1; } nOut += printf("Content-Range: bytes %d-%d/%d\r\n", rangeStart, rangeEnd, (int)pStat->st_size); pStat->st_size = rangeEnd + 1 - rangeStart; }else{ StartResponse("200 OK"); rangeStart = 0; } nOut += DateTag("Last-Modified", pStat->st_mtime); nOut += printf("Cache-Control: max-age=%d\r\n", mxAge); nOut += printf("ETag: \"%s\"\r\n", zETag); nOut += printf("Content-type: %s\r\n",zContentType); nOut += printf("Content-length: %d\r\n\r\n",(int)pStat->st_size); fflush(stdout); if( strcmp(zMethod,"HEAD")==0 ){ MakeLogEntry(0, 2); /* LOG: Normal HEAD reply */ fclose(in); fflush(stdout); return 1; } if( useTimeout ) alarm(30 + pStat->st_size/1000); #ifdef linux { off_t offset = rangeStart; nOut += sendfile(fileno(stdout), fileno(in), &offset, pStat->st_size); } #else { int c; int n = (int)pStat->st_size; while( rangeStart>0 && getc(in)!=EOF ){ rangeStart--; } while( (c = getc(in))!=EOF && n>0 ){ putc(c,stdout); nOut++; n--; } } #endif fclose(in); return 0; } |
︙ | ︙ | |||
1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 | while( fgets(zLine,sizeof(zLine),in) && !isspace((unsigned char)zLine[0]) ){ if( strncasecmp(zLine,"Location:",9)==0 ){ StartResponse("302 Redirect"); RemoveNewline(zLine); z = &zLine[10]; while( isspace(*(unsigned char*)z) ){ z++; } nOut += printf("Location: %s\r\n",z); }else if( strncasecmp(zLine,"Status:",7)==0 ){ int i; for(i=7; isspace((unsigned char)zLine[i]); i++){} nOut += printf("%s %s", zProtocol, &zLine[i]); strncpy(zReplyStatus, &zLine[i], 3); zReplyStatus[3] = 0; statusSent = 1; | > > < < | | | > > > > > > > | > | | > > > > > > > > > | > > > > > > > | > < < < < < > | 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 | while( fgets(zLine,sizeof(zLine),in) && !isspace((unsigned char)zLine[0]) ){ if( strncasecmp(zLine,"Location:",9)==0 ){ StartResponse("302 Redirect"); RemoveNewline(zLine); z = &zLine[10]; while( isspace(*(unsigned char*)z) ){ z++; } nOut += printf("Location: %s\r\n",z); rangeEnd = 0; }else if( strncasecmp(zLine,"Status:",7)==0 ){ int i; for(i=7; isspace((unsigned char)zLine[i]); i++){} nOut += printf("%s %s", zProtocol, &zLine[i]); strncpy(zReplyStatus, &zLine[i], 3); if( atoi(&zLine[i])!=200 ) rangeEnd = 0; zReplyStatus[3] = 0; statusSent = 1; }else if( strncasecmp(zLine, "Content-length:", 15)==0 ){ seenContentLength = 1; contentLength = atoi(zLine+15); }else{ size_t nLine = strlen(zLine); if( nRes+nLine >= nMalloc ){ nMalloc += nMalloc + nLine*2; aRes = realloc(aRes, nMalloc+1); if( aRes==0 ){ Malfunction(600, "Out of memory: %d bytes", nMalloc); } } memcpy(aRes+nRes, zLine, nLine); nRes += nLine; } } /* Copy everything else thru without change or analysis. */ if( rangeEnd>0 && seenContentLength && rangeStart<contentLength ){ StartResponse("206 Partial Content"); if( rangeEnd>=contentLength ){ rangeEnd = contentLength-1; } nOut += printf("Content-Range: bytes %d-%d/%d\r\n", rangeStart, rangeEnd, contentLength); contentLength = rangeEnd + 1 - rangeStart; }else{ StartResponse("200 OK"); } if( useTimeout ) alarm(60*5); if( nRes>0 ){ aRes[nRes] = 0; printf("%s", aRes); nOut += nRes; nRes = 0; } if( seenContentLength ){ nOut += printf("Content-length: %d\r\n\r\n", contentLength); while( rangeStart>0 && getc(in)!=EOF ){ rangeStart--; } while( (contentLength--)>0 && (c = getc(in))!=EOF ){ putc(c,stdout); nOut++; } }else{ while( (c = getc(in))!=EOF ){ if( nRes>=nMalloc ){ nMalloc = nMalloc*2; aRes = realloc(aRes, nMalloc+1); if( aRes==0 ){ Malfunction(610, "Out of memory: %d bytes", nMalloc); } } aRes[nRes++] = c; } aRes[nRes] = 0; nOut += printf("Content-length: %d\r\n\r\n%s", (int)nRes, aRes); } free(aRes); fclose(in); } /* ** Send an SCGI request to a host identified by zFile and process the ** reply. */ |
︙ | ︙ | |||
1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 | */ zCookie = 0; zAuthType = 0; zRemoteUser = 0; zReferer = 0; zIfNoneMatch = 0; zIfModifiedSince = 0; while( fgets(zLine,sizeof(zLine),stdin) ){ char *zFieldName; char *zVal; #ifdef LOG_HEADER if( hdrLog ) fprintf(hdrLog, "%s", zLine); #endif | > | 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 | */ zCookie = 0; zAuthType = 0; zRemoteUser = 0; zReferer = 0; zIfNoneMatch = 0; zIfModifiedSince = 0; rangeEnd = 0; while( fgets(zLine,sizeof(zLine),stdin) ){ char *zFieldName; char *zVal; #ifdef LOG_HEADER if( hdrLog ) fprintf(hdrLog, "%s", zLine); #endif |
︙ | ︙ | |||
1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 | } }else if( strcasecmp(zFieldName,"Authorization:")==0 ){ zAuthType = GetFirstElement(StrDup(zVal), &zAuthArg); }else if( strcasecmp(zFieldName,"If-None-Match:")==0 ){ zIfNoneMatch = StrDup(zVal); }else if( strcasecmp(zFieldName,"If-Modified-Since:")==0 ){ zIfModifiedSince = StrDup(zVal); } } #ifdef LOG_HEADER if( hdrLog ) fclose(hdrLog); #endif /* Disallow requests from certain clients */ | > > > > > > > > > > > | 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 | } }else if( strcasecmp(zFieldName,"Authorization:")==0 ){ zAuthType = GetFirstElement(StrDup(zVal), &zAuthArg); }else if( strcasecmp(zFieldName,"If-None-Match:")==0 ){ zIfNoneMatch = StrDup(zVal); }else if( strcasecmp(zFieldName,"If-Modified-Since:")==0 ){ zIfModifiedSince = StrDup(zVal); }else if( strcasecmp(zFieldName,"Range:")==0 && strcmp(zMethod,"GET")==0 ){ int x1 = 0, x2 = 0; int n = sscanf(zVal, "bytes=%d-%d", &x1, &x2); if( n==2 && x1>=0 && x2>=x1 ){ rangeStart = x1; rangeEnd = x2; }else if( n==1 && x1>0 ){ rangeStart = x1; rangeEnd = 0x7fffffff; } } } #ifdef LOG_HEADER if( hdrLog ) fclose(hdrLog); #endif /* Disallow requests from certain clients */ |
︙ | ︙ | |||
1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 | "Content-type: text/plain\r\n" "\r\n" "Too much POST data\n" ); MakeLogEntry(0, 270); /* LOG: Request too large */ exit(0); } sprintf(zTmpNamBuf, "/tmp/-post-data-XXXXXX"); zTmpNam = zTmpNamBuf; if( mkstemp(zTmpNam)<0 ){ Malfunction(280, /* LOG: mkstemp() failed */ "Cannot create a temp file in which to store POST data"); } out = fopen(zTmpNam,"wb"); | > | 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 | "Content-type: text/plain\r\n" "\r\n" "Too much POST data\n" ); MakeLogEntry(0, 270); /* LOG: Request too large */ exit(0); } rangeEnd = 0; sprintf(zTmpNamBuf, "/tmp/-post-data-XXXXXX"); zTmpNam = zTmpNamBuf; if( mkstemp(zTmpNam)<0 ){ Malfunction(280, /* LOG: mkstemp() failed */ "Cannot create a temp file in which to store POST data"); } out = fopen(zTmpNam,"wb"); |
︙ | ︙ |