Node.js request模块 透传cookie

本文介绍如何使用Node.js的Express框架和Request模块实现跨域请求,并透传Cookie,确保前后端交互中Cookie的正确传递。文章详细展示了设置请求头、处理响应头以及自定义Cookie的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

版本:

request:2.85.0

express:4.14.1

代码:

var express = require('express');
var router = express.Router();
var request = require('request');

router.get('/token', function(req, res, next) {
    var url = 'http://127.0.0.1:8080/xxx/token';

    var opts = {
        url: url,
        method: 'GET',
        // ************** 透传请求中的cookie **************
        headers: {
            'Cookie': req.header("Cookie"),
        }
    };

    request.get(opts,
        function (err, response, body) {
            if (response.statusCode === 200) {
                var data = JSON.parse(response.body);
                console.log(data);
                // ************** 透传响应中的cookie **************
                if (response.headers['set-cookie']) {
                    res.setHeader("set-cookie", response.headers['set-cookie']);
                }
                // ************** 自定义cookie **************
                res.cookie('tc', 'test-cookie', {maxAge: 2 * 60 * 60 * 1000, httpOnly: true});
                return res.status(response.statusCode).json(data);
            } else {
                return res.status(response.statusCode).json({status:1, msg:'系统异常', data:{}});
            }
        });

});

module.exports = router;

 

import type { AxiosInstance, AxiosResponse } from 'axios' import type { McAxiosRequestConfig } from './axios' import axios from './axios' type RequestMethod = 'get' | 'post' | 'delete' | 'put' class Request { private instance: AxiosInstance constructor(params: AxiosInstance) { this.instance = params } public get(url: string, config: any = {}): Promise<AxiosResponse<any>> { return this.request('get', url, config) } public post( url: string, data: any = {}, config: McAxiosRequestConfig = {}, ): Promise<AxiosResponse<any>> { return this.request('post', url, data, config) } public put( url: string, data: any = {}, config: McAxiosRequestConfig = {}, ): Promise<AxiosResponse<any>> { return this.request('put', url, data, config) } public delete( url: string, data: any = {}, config: McAxiosRequestConfig = {}, ): Promise<AxiosResponse<any>> { return this.request('delete', url, data, config) } // 新增流式处理方法 public stream( url: string, method: RequestMethod = 'get', config: McAxiosRequestConfig & { responseType?: 'stream' | 'arraybuffer' | 'blob' onData?: (chunk: Uint8Array | ArrayBuffer | Blob) => void onError?: (error: Error) => void onComplete?: () => void } = {}, ): Promise<AxiosResponse> { const { onData, onError, onComplete, ...axiosConfig } = config return new Promise((resolve, reject) => { this.instance({ method, url, ...axiosConfig, onDownloadProgress: (progressEvent) => { if (progressEvent.event.target instanceof ReadableStream) { const reader = progressEvent.event.target.getReader() const readChunk = () => { reader.read() .then(({ done, value }: any) => { if (done) { onComplete?.() return } onData?.(value) readChunk() }) .catch((err: any) => { onError?.(err) reject(err) }) } readChunk() } // 处理ArrayBuffer类型 else if (progressEvent.loaded && progressEvent.total) { const percent = Math.round((progressEvent.loaded * 100) / progressEvent.total) console.log(`Download progress: ${percent}%`) } }, responseType: config.responseType || 'stream', }) .then((response) => { // 直接返回原始响应 resolve(response) }) .catch((error) => { onError?.(error) reject(error) }) }) } // 修改后的下载方法 public download( url: string, params: any = {}, filename?: string, method: RequestMethod = 'get', config: McAxiosRequestConfig = {}, ): Promise<any> { return this.stream(url, method, { ...config, params, responseType: 'blob', }).then((res) => { // 创建下载链接 const url = window.URL.createObjectURL(res.data) const a = document.createElement('a') a.style.display = 'none' a.href = url a.download = filename || `download_${Date.now()}` document.body.appendChild(a) a.click() window.URL.revokeObjectURL(url) document.body.removeChild(a) }) } private async request( method: RequestMethod, url: string, config: McAxiosRequestConfig, ...params: any ) { return await this.instance[method](url, config, ...params) } } export const request = new Request(axios) 这是封装的axios请求文件;// 测试管理 - 测试任务 - 任务详情 - 对比结果 - 查看任务步骤音频文件 async function checkTaskResultAudio(stepId: string) { const apiUrl = `/test/task/result/download/audio/${stepId}` return request.stream(apiUrl, 'get', { responseType: 'arraybuffer', onData: (chunk) => { console.log(chunk) }, }) }这是我请求接口的方式;这是拦截// import { systemApi } from '@/api' // import { getDefaultLanguage, StorageUtils } from '@/common/utils/StorageUtils' // import { apiWhiteList, BASE_URL } from '@/config' import { router } from '@/router/index' import { clearToken, getToken, useElementPlus } from '@/utils' // import { useUserStore } from '@/store/user' import axios, { type AxiosRequestConfig } from 'axios' const { error, warning } = useElementPlus() const apiWhiteList = ['/auth/oauth/token'] export class McAxiosRequestConfig implements AxiosRequestConfig<any> { extraConfig?: { tokenRetryCount: number } headers?: any baseURL?: string timeout?: number method?: string data?: any params?: any responseType?: any } const _refreshObj: { isRefreshing: boolean requests: Array<Function> } = { isRefreshing: false, requests: [], } const BASE_URL = import.meta.env.VITE_BASE_URL const instance = axios.create({ baseURL: BASE_URL, timeout: 5 * 60 * 1000, headers: { 'Content-Type': 'application/json', }, }) instance.interceptors.request.use( (config: any) => { if (config && config?.headers) { config.headers['X-Requested-With'] = 'XMLHttpRequest' config.headers['Request-Start'] = new Date().getTime() } if (!config.extraConfig?.tokenRetryCount) { config.extraConfig = { tokenRetryCount: 0, } } // 判断本地是否有token(保存在cookie中,便于设置过期时间) const accessToken = getToken() || '' if (!apiWhiteList.includes(config.url) && accessToken) { config.headers.Authorization = `Bearer ${accessToken}` } if (config.method?.toUpperCase() === 'GET') { config.params = { ...config.params, _t: new Date().getTime() } } if (Object.values(config.headers).includes('application/x-www-form-urlencoded')) { config.data = JSON.stringify(config.data) } return config }, (err) => { return Promise.reject(new Error(err)) }, ) instance.interceptors.response.use( (response) => { console.log(response, 'response') if (response.status === 200) { if (response.data) { // token过期,强制退出登录 if (response.data.code === 401) { clearToken() router.replace('/login') } const { code, msg = '' } = response.data if (code !== 0) { window.$message.error(msg) throw new Error(msg) // return Promise.reject(new Error(msg)) } return response.data } } return response }, (err) => { if (axios.isCancel(err)) { // 取消的请求,不报错 return } if (err.message.includes('timeout')) { return error('请求超时') } warning(err) return Promise.reject(new Error(err)) }, ) export default instance
最新发布
05-29
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值