mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-02 03:49:37 +00:00
Bug 811646 - Redirect handling so each request goes direct to the final destination path and server. r=rstrong
This commit is contained in:
parent
b9dc30212f
commit
84a17ce89e
@ -930,7 +930,7 @@ FunctionEnd
|
|||||||
Function StartDownload
|
Function StartDownload
|
||||||
${NSD_KillTimer} StartDownload
|
${NSD_KillTimer} StartDownload
|
||||||
InetBgDL::Get "${URLStubDownload}" "$PLUGINSDIR\download.exe" \
|
InetBgDL::Get "${URLStubDownload}" "$PLUGINSDIR\download.exe" \
|
||||||
/CONNECTTIMEOUT 120 /RECEIVETIMEOUT 120 /END
|
/RANGEREQUEST /CONNECTTIMEOUT 120 /RECEIVETIMEOUT 120 /END
|
||||||
StrCpy $4 ""
|
StrCpy $4 ""
|
||||||
${NSD_CreateTimer} OnDownload ${DownloadIntervalMS}
|
${NSD_CreateTimer} OnDownload ${DownloadIntervalMS}
|
||||||
${If} ${FileExists} "$INSTDIR\${TO_BE_DELETED}"
|
${If} ${FileExists} "$INSTDIR\${TO_BE_DELETED}"
|
||||||
|
@ -32,7 +32,7 @@ PTSTR g_N_Vars;
|
|||||||
|
|
||||||
DWORD g_ConnectTimeout = 0;
|
DWORD g_ConnectTimeout = 0;
|
||||||
DWORD g_ReceiveTimeout = 0;
|
DWORD g_ReceiveTimeout = 0;
|
||||||
|
bool g_WantRangeRequest = false;
|
||||||
|
|
||||||
#define NSISPI_INITGLOBALS(N_CCH, N_Vars) do { \
|
#define NSISPI_INITGLOBALS(N_CCH, N_Vars) do { \
|
||||||
g_N_CCH = N_CCH; \
|
g_N_CCH = N_CCH; \
|
||||||
@ -319,10 +319,15 @@ diegle:
|
|||||||
goto diegle;
|
goto diegle;
|
||||||
}
|
}
|
||||||
|
|
||||||
const DWORD IOURedirFlags = INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP | INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS;
|
const DWORD IOURedirFlags = INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP |
|
||||||
const DWORD IOUCacheFlags = INTERNET_FLAG_RESYNCHRONIZE | INTERNET_FLAG_NO_CACHE_WRITE;
|
INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS;
|
||||||
|
const DWORD IOUCacheFlags = INTERNET_FLAG_RESYNCHRONIZE |
|
||||||
|
INTERNET_FLAG_NO_CACHE_WRITE |
|
||||||
|
INTERNET_FLAG_PRAGMA_NOCACHE |
|
||||||
|
INTERNET_FLAG_RELOAD;
|
||||||
const DWORD IOUCookieFlags = INTERNET_FLAG_NO_COOKIES;
|
const DWORD IOUCookieFlags = INTERNET_FLAG_NO_COOKIES;
|
||||||
DWORD IOUFlags = IOURedirFlags | IOUCacheFlags | IOUCookieFlags | INTERNET_FLAG_NO_UI | INTERNET_FLAG_EXISTING_CONNECT;
|
DWORD IOUFlags = IOURedirFlags | IOUCacheFlags | IOUCookieFlags |
|
||||||
|
INTERNET_FLAG_NO_UI | INTERNET_FLAG_EXISTING_CONNECT;
|
||||||
|
|
||||||
WCHAR protocol[16];
|
WCHAR protocol[16];
|
||||||
WCHAR server[128];
|
WCHAR server[128];
|
||||||
@ -337,18 +342,19 @@ diegle:
|
|||||||
|
|
||||||
DWORD context;
|
DWORD context;
|
||||||
hInetCon = InternetConnect(hInetSes, server, port, NULL, NULL,
|
hInetCon = InternetConnect(hInetSes, server, port, NULL, NULL,
|
||||||
INTERNET_SERVICE_HTTP, 0, (unsigned long)&context);
|
INTERNET_SERVICE_HTTP, IOUFlags,
|
||||||
|
(unsigned long)&context);
|
||||||
if (!hInetCon)
|
if (!hInetCon)
|
||||||
{
|
{
|
||||||
goto diegle;
|
goto diegle;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup a buffer of size 256KiB to store the downloaded data.
|
// Setup a buffer of size 256KiB to store the downloaded data.
|
||||||
// Get at most 2MiB at a time from the partial HTTP Range requests.
|
// Get at most 4MiB at a time from the partial HTTP Range requests.
|
||||||
// Biffer buffers will be faster.
|
// Biffer buffers will be faster.
|
||||||
// cbRangeReadBufXF should be a multiple of cbBufXF.
|
// cbRangeReadBufXF should be a multiple of cbBufXF.
|
||||||
const UINT cbBufXF = 262144;
|
const UINT cbBufXF = 262144;
|
||||||
const UINT cbRangeReadBufXF = 2097152;
|
const UINT cbRangeReadBufXF = 4194304;
|
||||||
BYTE bufXF[cbBufXF];
|
BYTE bufXF[cbBufXF];
|
||||||
|
|
||||||
// Up the default internal buffer size from 4096 to internalReadBufferSize.
|
// Up the default internal buffer size from 4096 to internalReadBufferSize.
|
||||||
@ -372,24 +378,87 @@ diegle:
|
|||||||
&g_ReceiveTimeout, sizeof(DWORD));
|
&g_ReceiveTimeout, sizeof(DWORD));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Obtain the file size using a HEAD request.
|
HINTERNET hInetFile;
|
||||||
// Some proxy servers will hold up an entire download for GET requests, so
|
DWORD cbio = sizeof(DWORD);
|
||||||
// HEAD is important here.
|
|
||||||
HINTERNET hInetFile = HttpOpenRequest(hInetCon, L"HEAD",
|
|
||||||
path, NULL, NULL, NULL, 0, 0);
|
|
||||||
if (!hInetFile)
|
|
||||||
{
|
|
||||||
goto diegle;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!HttpSendRequest(hInetFile, NULL, 0, NULL, 0))
|
// Keep looping until we don't have a redirect anymore
|
||||||
{
|
int redirectCount = 0;
|
||||||
goto diegle;
|
for (;;) {
|
||||||
|
// Make sure we aren't stuck in some kind of infinite redirect loop.
|
||||||
|
if (redirectCount > 15) {
|
||||||
|
goto diegle;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If a range request was specified, first do a HEAD request
|
||||||
|
hInetFile = HttpOpenRequest(hInetCon, g_WantRangeRequest ? L"HEAD" : L"GET",
|
||||||
|
path, NULL, NULL, NULL,
|
||||||
|
INTERNET_FLAG_NO_AUTO_REDIRECT |
|
||||||
|
INTERNET_FLAG_PRAGMA_NOCACHE |
|
||||||
|
INTERNET_FLAG_RELOAD, 0);
|
||||||
|
if (!hInetFile)
|
||||||
|
{
|
||||||
|
goto diegle;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!HttpSendRequest(hInetFile, NULL, 0, NULL, 0))
|
||||||
|
{
|
||||||
|
goto diegle;
|
||||||
|
}
|
||||||
|
|
||||||
|
WCHAR responseText[256];
|
||||||
|
cbio = sizeof(responseText);
|
||||||
|
if (!HttpQueryInfo(hInetFile,
|
||||||
|
HTTP_QUERY_STATUS_CODE,
|
||||||
|
responseText, &cbio, NULL))
|
||||||
|
{
|
||||||
|
goto diegle;
|
||||||
|
}
|
||||||
|
|
||||||
|
int statusCode = _wtoi(responseText);
|
||||||
|
if (statusCode == HTTP_STATUS_REDIRECT ||
|
||||||
|
statusCode == HTTP_STATUS_MOVED) {
|
||||||
|
redirectCount++;
|
||||||
|
WCHAR URLBuffer[2048];
|
||||||
|
cbio = sizeof(URLBuffer);
|
||||||
|
if (!HttpQueryInfo(hInetFile,
|
||||||
|
HTTP_QUERY_LOCATION,
|
||||||
|
(DWORD*)URLBuffer, &cbio, NULL))
|
||||||
|
{
|
||||||
|
goto diegle;
|
||||||
|
}
|
||||||
|
|
||||||
|
WCHAR protocol2[16];
|
||||||
|
WCHAR server2[128];
|
||||||
|
WCHAR path2[1024];
|
||||||
|
INTERNET_PORT port2;
|
||||||
|
BasicParseURL<16, 128, 1024>(URLBuffer, &protocol2, &port2, &server2, &path2);
|
||||||
|
// Check if we need to reconnect to a new server
|
||||||
|
if (wcscmp(protocol, protocol2) || wcscmp(server, server2) ||
|
||||||
|
port != port2) {
|
||||||
|
wcscpy(server, server2);
|
||||||
|
port = port2;
|
||||||
|
InternetCloseHandle(hInetCon);
|
||||||
|
hInetCon = InternetConnect(hInetSes, server, port, NULL, NULL,
|
||||||
|
INTERNET_SERVICE_HTTP, IOUFlags,
|
||||||
|
(unsigned long)&context);
|
||||||
|
if (!hInetCon)
|
||||||
|
{
|
||||||
|
goto diegle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wcscpy(path, path2);
|
||||||
|
|
||||||
|
// Close the existing handle because we'll be issuing a new request
|
||||||
|
// with the new request path.
|
||||||
|
InternetCloseHandle(hInetFile);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the file length via the Content-Length header
|
// Get the file length via the Content-Length header
|
||||||
FILESIZE_T cbThisFile;
|
FILESIZE_T cbThisFile;
|
||||||
DWORD cbio = sizeof(cbThisFile);
|
cbio = sizeof(cbThisFile);
|
||||||
if (!HttpQueryInfo(hInetFile,
|
if (!HttpQueryInfo(hInetFile,
|
||||||
HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER,
|
HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER,
|
||||||
&cbThisFile, &cbio, NULL))
|
&cbThisFile, &cbio, NULL))
|
||||||
@ -400,7 +469,7 @@ diegle:
|
|||||||
// Determine if we should use byte range requests. We want to use it if:
|
// Determine if we should use byte range requests. We want to use it if:
|
||||||
// 1. Server accepts byte range requests
|
// 1. Server accepts byte range requests
|
||||||
// 2. The size of the file is known and more than our Range buffer size.
|
// 2. The size of the file is known and more than our Range buffer size.
|
||||||
bool useRangeRequest = true;
|
bool shouldUseRangeRequest = true;
|
||||||
WCHAR rangeRequestAccepted[64] = { '\0' };
|
WCHAR rangeRequestAccepted[64] = { '\0' };
|
||||||
cbio = sizeof(rangeRequestAccepted);
|
cbio = sizeof(rangeRequestAccepted);
|
||||||
if (cbThisFile != FILESIZE_UNKNOWN && cbThisFile <= cbRangeReadBufXF ||
|
if (cbThisFile != FILESIZE_UNKNOWN && cbThisFile <= cbRangeReadBufXF ||
|
||||||
@ -408,17 +477,20 @@ diegle:
|
|||||||
HTTP_QUERY_ACCEPT_RANGES,
|
HTTP_QUERY_ACCEPT_RANGES,
|
||||||
(LPDWORD)rangeRequestAccepted, &cbio, NULL))
|
(LPDWORD)rangeRequestAccepted, &cbio, NULL))
|
||||||
{
|
{
|
||||||
useRangeRequest = false;
|
shouldUseRangeRequest = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
useRangeRequest = wcsstr(rangeRequestAccepted, L"bytes") != 0 &&
|
shouldUseRangeRequest = wcsstr(rangeRequestAccepted, L"bytes") != 0 &&
|
||||||
cbThisFile != FILESIZE_UNKNOWN;
|
cbThisFile != FILESIZE_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the server doesn't have range request support or doesn't have a
|
// If the server doesn't have range request support or doesn't have a
|
||||||
// Content-Length header, then get everything all at once.
|
// Content-Length header, then get everything all at once.
|
||||||
if (!useRangeRequest)
|
// If the user didn't want a range request, then we already issued the GET
|
||||||
|
// request earlier. If the user did want a range request, then we issued only
|
||||||
|
// a HEAD so far.
|
||||||
|
if (g_WantRangeRequest && !shouldUseRangeRequest)
|
||||||
{
|
{
|
||||||
InternetCloseHandle(hInetFile);
|
InternetCloseHandle(hInetFile);
|
||||||
InternetCloseHandle(hInetCon);
|
InternetCloseHandle(hInetCon);
|
||||||
@ -428,6 +500,7 @@ diegle:
|
|||||||
{
|
{
|
||||||
goto diegle;
|
goto diegle;
|
||||||
}
|
}
|
||||||
|
|
||||||
// For some reason this also needs to be set on the hInetFile and
|
// For some reason this also needs to be set on the hInetFile and
|
||||||
// not just the connection.
|
// not just the connection.
|
||||||
if (g_ReceiveTimeout > 0)
|
if (g_ReceiveTimeout > 0)
|
||||||
@ -441,12 +514,14 @@ diegle:
|
|||||||
{
|
{
|
||||||
DWORD cbio = 0,cbXF = 0;
|
DWORD cbio = 0,cbXF = 0;
|
||||||
// If we know the file size, download it in chunks
|
// If we know the file size, download it in chunks
|
||||||
if (useRangeRequest && cbThisFile != g_cbCurrXF)
|
if (g_WantRangeRequest && shouldUseRangeRequest && cbThisFile != g_cbCurrXF)
|
||||||
{
|
{
|
||||||
// Close the previous request, but not the connection
|
// Close the previous request, but not the connection
|
||||||
InternetCloseHandle(hInetFile);
|
InternetCloseHandle(hInetFile);
|
||||||
hInetFile = HttpOpenRequest(hInetCon, L"GET", path,
|
hInetFile = HttpOpenRequest(hInetCon, L"GET", path,
|
||||||
NULL, NULL, NULL, 0, 0);
|
NULL, NULL, NULL,
|
||||||
|
INTERNET_FLAG_PRAGMA_NOCACHE |
|
||||||
|
INTERNET_FLAG_RELOAD, 0);
|
||||||
if (!hInetFile)
|
if (!hInetFile)
|
||||||
{
|
{
|
||||||
// TODO: we could add retry here to be more tolerant
|
// TODO: we could add retry here to be more tolerant
|
||||||
@ -512,7 +587,7 @@ diegle:
|
|||||||
|
|
||||||
// Avoid an extra call to InternetReadFile if we already read everything
|
// Avoid an extra call to InternetReadFile if we already read everything
|
||||||
// in the current request
|
// in the current request
|
||||||
if (cbio == cbRangeReadBufXF && useRangeRequest)
|
if (cbio == cbRangeReadBufXF && shouldUseRangeRequest)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -560,6 +635,7 @@ diegle:
|
|||||||
NSISPIEXPORTFUNC Get(HWND hwndNSIS, UINT N_CCH, TCHAR*N_Vars, NSIS::stack_t**ppST, NSIS::xparams_t*pX)
|
NSISPIEXPORTFUNC Get(HWND hwndNSIS, UINT N_CCH, TCHAR*N_Vars, NSIS::stack_t**ppST, NSIS::xparams_t*pX)
|
||||||
{
|
{
|
||||||
pX->RegisterPluginCallback(g_hInst, NSISPluginCallback);
|
pX->RegisterPluginCallback(g_hInst, NSISPluginCallback);
|
||||||
|
g_WantRangeRequest = false;
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
NSIS::stack_t*pURL = StackPopItem(ppST);
|
NSIS::stack_t*pURL = StackPopItem(ppST);
|
||||||
@ -568,7 +644,12 @@ NSISPIEXPORTFUNC Get(HWND hwndNSIS, UINT N_CCH, TCHAR*N_Vars, NSIS::stack_t**ppS
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lstrcmpi(pURL->text, _T("/connecttimeout")) == 0)
|
if (lstrcmpi(pURL->text, _T("/rangerequest")) == 0)
|
||||||
|
{
|
||||||
|
g_WantRangeRequest = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (lstrcmpi(pURL->text, _T("/connecttimeout")) == 0)
|
||||||
{
|
{
|
||||||
NSIS::stack_t*pConnectTimeout = StackPopItem(ppST);
|
NSIS::stack_t*pConnectTimeout = StackPopItem(ppST);
|
||||||
g_ConnectTimeout = _tcstol(pConnectTimeout->text, NULL, 10) * 1000;
|
g_ConnectTimeout = _tcstol(pConnectTimeout->text, NULL, 10) * 1000;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user