Alv*_*eda 5 redirect fetch react-native
我正在尝试使用没有 API 的 React Native 来爬网。它是用 PHP 编写的。
要登录用户,必须发送 POST 请求。响应返回一个带有 PHPSessid cookie 的 cookie,我必须捕获它以在后续请求中使用。
我想捕获 cookie 值,购买 POST 响应是 302 并且重定向是自动跟随的,所以我看不到 cookie。在节点中,我可以使用redirect:manual
,但它在本机反应中不起作用。
cookie 在后续请求中自动发送,我正在尝试使用 react-native-cookie 手动管理 cookie,我想知道是否可能。
您知道停止重定向的方法吗?
我一直在检查代码,我所做的如下:
这里有一些代码,但重要的是您执行第一个空登录请求,捕获 PHPSessid 并使用该 PHPSessid 启动真正的登录请求。
这将是主要功能:
import Cookie from 'react-native-cookie';
// I think this is used only to clear the cookies
function login(user, pass){
// clear all cookies for all domains
// We need to start withouth authorization token
Cookie.clear();
const makeLoginRequest = (sessid) =>
makeLoginRequestForUserAndPass(user,pass,sessid);
return makeInitialRequest()
.then(getSessionIDFromResponse)
.then(makeLoginRequest)
.then(checkIfLoggedAndGetSessionID);
}
Run Code Online (Sandbox Code Playgroud)
初始请求是对登录脚本的请求。请注意,我使用 GET 因为它适用于我的网站,也许需要一个空帖子:
function makeInitialRequest() {
const INIT_PATH = '/index.php?r=site/login';
const INIT_URL = site + INIT_PATH;
const request = new Request(INIT_URL, options....);
return fetch(request);
}
Run Code Online (Sandbox Code Playgroud)
我们在响应中得到了会话 ID。我使用一个简单的正则表达式来提取它。请注意,我们尚未登录;PHP 已经创建了一个会话,这就是我们这里的内容:
function getSessionIDFromResponse(response) {
return getPHPSessIdFromCookie(response.headers.get('set-cookie'));
}
function getPHPSessIdFromCookie(header) {
const regex = /PHPSESSID=(\w*)/;
const match = regex.exec(header);
return match ? match[1] : '';
}
Run Code Online (Sandbox Code Playgroud)
现在是登录请求。请注意,我无法在这里停止重定向,但我不必这样做,因为我们稍后可以拥有 PHPSessid。重定向必须在 POST 请求中设置为手动:
function makeLoginRequestForUserAndPass(user, pass, sessid) {
const request = buildLoginRequest(user, pass, sessid);
return fetch(request);
}
// This is where we build the real login request
function buildLoginRequest(user, pass, sessid) {
const LOGIN_PATH = '/index.php?r=site/login';
const LOGIN_URL = site + LOGIN_PATH;
const fields = [
{name: 'LoginForm[username]', value: user},
{name: 'LoginForm[password]', value: pass},
etc...
];
const data = translateFieldsToURLEncodedData(fields);
const headers = {
'Content-type': 'application/x-www-form-urlencoded',
Cookie: `PHPSESSID=${sessid}`, // HERE is where you put the data
};
const options = { method: 'POST',
headers: headers,
mode: 'cors',
cache: 'default',
agent: proxy,
body: data,
redirect: 'manual' // VERY IMPORTANT: if you don't do it, the cookie is lost
};
return new Request(LOGIN_URL, options);
}
// Simple utility function
function translateFieldsToURLEncodedData(fields){
let pairs = fields.map( (field) => {
return encodeURIComponent(field.name) + '=' + encodeURIComponent(field.value);
});
return pairs.join('&');
}
Run Code Online (Sandbox Code Playgroud)
这是最后一部分。为了查看我是否已登录,我检查了响应中是否包含属于登录错误页面的文本。我还得到了 PHPSessid (我认为它在登录后发生了变化,不确定,那是一年前的事)但我不知道我是否使用过它,我相信它会自动包含在后续请求中。我认为这部分可以简化和改进:
function checkIfLoggedAndGetSessionID(response) {
return (
checkIfLoggedOK(response)
.then(() => getSessionIDFromResponse(response))
);
}
function checkIfLoggedOK(response){
return getTextFromResponse(response)
.then(throwErrorIfNotLogedOk);
}
function getTextFromResponse(response) {
return response.text();
}
function throwErrorIfNotLogedOk(page) {
if(isErrorPage(page)) throw new Error("Login failed");
}
function isErrorPage(text) {
const ERROR_MESSAGE = 'Something that appears in login failed page of your site';
let n = text.search(ERROR_MESSAGE);
return n !== -1;
}
Run Code Online (Sandbox Code Playgroud)
希望这会有用。
归档时间: |
|
查看次数: |
1630 次 |
最近记录: |