HTTP-запрос перенаправить и готовить ie обработка в node.js - PullRequest
0 голосов
/ 21 апреля 2020

Я пишу приложение в node.js, которое должно будет отправлять http-запросы на внешние веб-сайты и включать возможность входа и управления файлами cookie с этих сайтов, чтобы идентификатор сеанса всегда присутствовал в любых последующих запрашивать заголовки.

При выполнении аналогичных задач в Java это было просто, используя java. net .CookieHandler & java. net .CookieManager вместе с java. net .HttpURLConnection для выполнения запросов (я могу предоставить пример кода, это полезно, но пока я не хочу слишком сильно путать этот поток, поскольку основное внимание следует уделить реализации node.js): каждый раз, когда запрос сделано, повар ie корректно обновляется и поддерживается на основе ожидаемых заголовков ответа Set-Cook ie.

Для приложения node.js я пытаюсь использовать рестлер для запросов httq ^ 3.2 .2 и готовить ie -менеджер ^ 0.0.19. Похоже, что для этого требуется вручную устанавливать cook ie в заголовке запроса при отправке каждого запроса и обновлять cook ie на основе заголовков ответа при каждом завершении запроса. Пример кода для запроса входа в систему:

var _ = require('lodash'),
    restler = require('restler'),
    CM = require('cookie-manager'),
    cm = new CM();

var url = 'https://' + host1 + '/page';
    restlerOptions = {
        //Set the cookie for host1 in the request header
        headers : {'Cookie': cm.prepare( host1 )},
        followredirects: true,
        timeout: 5000,
        multipart: false,
        //post vars defined elsewhere for the request
        data: postVars
        };

//Various callback functions defined elsewhere for each request
restler.post(url,restlerOptions).on('complete',function(data,res){
    if (res.headers["set-cookie"] != null){
        //Loop through response cookies and add to cookie store for host1
        cm.store(
            host1,_.map(res.headers["set-cookie"], function(cookie){
                    return cookie.split(';')[0];
                }, "").join(";")
        );
    }
    successcallback(data,res);
}).on("timeout",function(){
    timeoutcallback();
}).on("error",function(err){
    errorcallback(err);
});

Проблема, с которой я сталкиваюсь, связана с перенаправлениями: иногда страницы входа для сторонних сайтов включают перенаправление на новый хост / поддомен и т. Д. c. То, что должно произойти, это то, что последующие запросы GET должны быть отправлены на новый хост, и для хоста перенаправления должен быть запущен новый повар ie. Окончательный редирект должен вернуться к исходному хосту, а оригинальный повар ie должен все еще использоваться. Пример заголовка запроса для этого процесса:

Req1 headers:
POST https://host1/page HTTP/1.1
Host: host1
Cookie: host1-cookie0=val0 //Cookie already present for host

Req1 response:
HTTP/1.1 302 Found
Set-cookie: host1-cookie1=val1
Set-cookie: host1-cookie2=val2
Location: https://host2/page

Req2 headers:
GET https://host2/page HTTP/1.1
Host: host2
<no cookie> //No cookie set yet for new host

Req2 response:
HTTP/1.1 302 Found
Set-cookie: host2-cookie1=val3
Set-cookie: host2-cookie2=val4
Location: https://host1/result

Req3 headers:
GET https://host1/result HTTP/1.1
Host: host1
Cookie: host1-cookie0=val0; host1-cookie1=val1; host1-cookie2=val2; //Cookies from Re1 response appended for host1

Req3 response:
HTTP/1.1 200 OK
Set-cookie: host1-cookie3=val5
Set-cookie: host1-cookie4=val6

Req4 headers:
GET https://host1/newpage HTTP/1.1
Host: host1
Cookie: host1-cookie0=val0; host1-cookie1=val1; host1-cookie2=val2; host1-cookie3=val5; host1-cookie4=val6 //All cookies set as expected for host1

Я вижу 3 проблемы:

  1. перенаправления сопровождаются POST
  2. того же самого повара ie, что устанавливается с исходным заголовком запроса, который используется во всех последующих запросах, независимо от последующих изменений хоста или любых файлов cookie, установленных из заголовков ответа на перенаправление (кажется, они устанавливаются только после получения ответа со статусом 200).
  3. Код установки cook ie, который я использую выше, должен перебирать все заголовки «Set-cook ie» и устанавливать первую часть каждой строки в cook ie. Однако, похоже, он делает это только для первого встречаемого заголовка «Set-Cook ie».

Пример ниже:

Req1 headers:
POST https://host1/page HTTP/1.1
Host: host1
Cookie: host1-cookie0=val0 //Cookie already present for host

Req1 response:
HTTP/1.1 302 Found
Set-cookie: host1-cookie1=val1
Set-cookie: host1-cookie2=val2
Location: https://host2/page

Req2 headers:
POST https://host2/page HTTP/1.1 //This should be GET not POST!
Host: host2
Cookie: host1-cookie0=val0 //This should not be set!

Req2 response:
HTTP/1.1 302 Found
Set-cookie: host2-cookie1=val3
Set-cookie: host2-cookie2=val4
Location: https://host1/result

Req3 headers:
POST https://host1/result HTTP/1.1 //This should be GET not POST!
Host: host1
Cookie: host1-cookie0=val0 //Req1 response cookies not set!

Req3 response:
HTTP/1.1 200 OK
Set-cookie: host1-cookie3=val5
Set-cookie: host1-cookie4=val6

Req4 headers:
GET https://host1/newpage HTTP/1.1
Host: host1
Cookie: host1-cookie0=val0; host1-cookie3=va51; //Only first cookie from Req3 response is appended

Является ли это ограничением библиотек restler / cook ie -manager, используемых таким образом, или же подход должен быть более умным (например, не используете автоматические c перенаправления, а вручную отправлять последующие запросы как GET с новым поваром ie)? Хотя создаваемое приложение ограничено для запуска в node.js, нет никаких ограничений на используемые библиотеки, поэтому, если разумно переключиться на другие библиотеки управления http / cook ie, я открыт для этого.

1 Ответ

0 голосов
/ 23 апреля 2020

1) Чтобы предотвратить автоматическое перенаправление c с помощью POST, мне пришлось добавить «followRedirects: false» в параметры исходного запроса, а затем вручную повторно отправить запрос GET, если код ответа был одним из [301,302,303] .

2) Так как перенаправления выполняются вручную, я смог вручную установить cook ie на основе нового домена для каждого запроса.

3) Не было необходимости извлекать значения из каждого заголовка «Set-cook ie» и добавьте их в одну строку - cook ie -manager сделает это автоматически.

Новый код, который работает (объединяет исправления 1,2,3 и выше):

var _ = require('lodash'),
    restler = require('restler'),
    CM = require('cookie-manager'),
    cm = new CM();

var url = 'https://' + host1 + '/page';
    restlerOptions = {
        //Set the cookie for host1 in the request header
        headers : {'Cookie': cm.prepare( host1 )},
        followRedirects: false,
        timeout: 5000,
        multipart: false,
        //post vars defined elsewhere for the request
        data: postVars
        };

//Various callback functions defined elsewhere for each request
restler.post(url,restlerOptions).on('complete',function(data,res){
    cm.store(host1, res.headers["set-cookie"]);
    if ([301,302,303].indexOf(res.statusCode) > -1){
        redirectcallback(res.headers["location"],successcallback,errorcallback,timeoutcallback);
    } else successCallback(data);
}).on("timeout",function(){
    timeoutcallback();
}).on("error",function(err){
    errorcallback(err);
});

function redirectCallback(url,successcallback,errorcallback,timeoutcallback){
    var options = {
        //Set the cookie for new host in the request header
        headers : {'Cookie': cm.prepare( getHostFromUrl(url) )}, //getHostFromUrl strips page/queryparams from URL - cookie manager doesn't seem to do this automatically
        followRedirects: false,
        timeout: 5000,
        };

    restler.get(url,restlerOptions).on('complete',function(data,res){
        cm.store(getHostFromUrl(url), res.headers["set-cookie"]);
        if ([301,302,303].indexOf(res.statusCode) > -1){
            redirectcallback(res.headers["location"],successcallback,errorcallback,timeoutcallback);
        } else successCallback(data);
    }).on("timeout",function(){
        timeoutcallback();
    }).on("error",function(err){
        errorcallback(err);
    });
}
...