express-http-proxy
express-http-proxy copied to clipboard
proxy multipart request
Hi there,
I have used your lib to create a proxy server. I use body-parser
and multer
middleware for parsing request bodies.
everything is going fine except for the multipart requests. is there anyway to proxy these requests?
Multipart requests are not explicitly supported right now, although I'd like to get this in soon. If you happen to have a sharable code snippet I could use for a test, I'd be happy to have it.
Actually I figured it out. Here is what I did:
- Main problem sovled when I ignored
body-parser
(json, urlencoded) for multipart requests. Before this igonringbodyContent
ofproxyReq
was empty. I did it like bellow:
const isMultipartRequest = function (req) {
let contentTypeHeader = req.headers['content-type'];
return contentTypeHeader && contentTypeHeader.indexOf('multipart') > -1;
};
const bodyParserJsonMiddleware = function () {
return function (req, res, next) {
if (isMultipartRequest(req)) {
return next();
}
return bodyParser.json()(req, res, next);
};
};
app.use(bodyParserJsonMiddleware());
- I removed using of multer because it's was useless in my case
- I added bellow code to dynamically change options for multipart requests:
const proxyMiddleware = function () {
return function (req, res, next) {
let reqAsBuffer = false;
let reqBodyEncoding = true;
let contentTypeHeader = req.headers['content-type'];
if (isMultipartRequest(req)) {
reqAsBuffer = true;
reqBodyEncoding = null;
}
return proxy(apiUrl, {
reqAsBuffer,
reqBodyEncoding,
timeout: timeout,
filter: function (req, res) {
//filter logic
},
decorateRequest: function (proxyReq, originalReq) {
//decorate logic
}
})(req, res, next);
};
};
app.use(apiUri, proxyMiddleware());
I still have issue with large file request forwarding. I added the limit: '4mb', but it still doesn't work with error "Request Entity Too Large". What is the work around for multipart file uploading? thanks!
@yannpeng can you add a failing test with a large file? I'd be happy to try to work this out.
Hello,
I am just checking in because the last traffic on this issue was several months ago. Does express-http-proxy support multipart form data and file uploads? Is anyone working on it? Im interested in using this with the multer package.
@nbroeking There is no explicit multipart support. I plan to address this in detail in priority order, but this is a little unattractive because I don't have much to start with. Are you interested in contributing a failing test or failing test case? This would accelerate action on this ticket.
Thanks,
@monkpow could you update readme to explicitly tell people that form upload just does not work and it is better to try, for example, http-proxy-middleware
?
thanks so much for your solutions @mahyarmobilab. I got yours to work with one important addition, setting parseReqBody: false
on the proxy config when multipart. So seeing it with your example as such:
const proxyMiddleware = function () {
return function (req, res, next) {
let reqAsBuffer = false;
let reqBodyEncoding = true;
let parseReqBody = true;
let contentTypeHeader = req.headers['content-type'];
if (isMultipartRequest(req)) {
reqAsBuffer = true;
reqBodyEncoding = null;
parseReqBody = false;
}
return proxy(apiUrl, {
reqAsBuffer,
reqBodyEncoding,
parseReqBody,
timeout: timeout,
filter: function (req, res) {
//filter logic
},
decorateRequest: function (proxyReq, originalReq) {
//decorate logic
}
})(req, res, next);
};
};
app.use(apiUri, proxyMiddleware());
At the time of my post, v1.x of this project is out, so readers make appropriate changes for API-breaking v1 changes.
@monkpow Thanks for this project. This is a pretty important feature to make smooth.
@yannpeng -- this parseReqBody: false
could be your issue too.
[Note: I corrected example code above replacing parseBodyReq
with parseReqBody
as pointed out by @mitchellirvin below.]
@btmurrell I'm not seeing "parseBodyReq" in the options for express-http-proxy, but I'm seeing "parseReqBody", did it get changed? Also, it notes that: "Note that setting this(parseReqBody) to false overrides reqAsBuffer and reqBodyEncoding below", and I've noticed that we're still setting values for those two options even though they get overridden (when it's a multipart req). I'm working with the code above to see what will run successfully in my app.
@monkpow is there a verified solution for multipart requests? even if it's not a part of the official package
sorry @mitchellirvin, i just noticed your comment. you were correct, and i updated above. as for reqAsBuffer
and reqBodyEncoding
, found the need to set them as above when multipart.
@btmurrell I noticed you do let contentTypeHeader = req.headers['content-type'];
, but then don't pass it into the proxy()
call. Did you mean to use it?
+1 for this request. is there any way we can proxy multipart requests using express-http-proxy? if not, any other suggestion for multipart file upload proxy may be using multer and express-http-proxy.
I ended up using this proxy instead. It handles multipart files swimmingly and was syntactically simpler.
var proxy = require('http-proxy-middleware');
/*
Service to proxy http requests: '/api' -> '/someproxydestination'
*/
app.use('/api', proxy({
target: '/proxydestination',
changeOrigin: true // needed for virtual hosted sites
}));
Hi mitchellirvin, do you have an example code for this upload? Thanks
@mitchellirvin I also tried http-proxy-middleware but we needed proxy for prod. So I tried @btmurrell's solution and it works. Thanks.
@algaly I'll get back to you with the boilerplate for the file upload that I ended up using.
@canbakis Is there a reason http-proxy-middleware
couldn't be used for prod? We've been using it to proxy service requests in a production environment for several months now. If it's not prod quality, let me know so we can fix it haha
@algaly sorry this is a little sloppy, short on time. this setup allows for a more elegant file input solution in angularjs
<input custom-onchange="handleFileUpload" class="ng-hide" id="input-file-id" type="file" name="file"/>
<input disabled placeholder="Choose a file" ng-model="ctrl.fileName" type="text"/>
<label for="input-file-id" class="button md-ink-ripple" ng-class="{'disabled': ctrl.uploading}">
<i class="icon_file_upload"></i>
</label>
// helper directive
angular.module('app')
.directive('customOnchange', customOnchange);
function customOnchange() {
return {
restrict: 'A',
link: function (scope, element, attrs) {
var onChangeHandler = scope.$eval(attrs.customOnchange);
element.on('change', onChangeHandler);
}
};
}
// in the controller
function handleFileUpload(ev) {
vm.file = ev.target.files[0];
}
Hey i had the same issue, and what solved the error for me was moving the body parser middleware declaration under the proxy declaration
so if you had
app.use(bodyParser(...))
app.use(URL, proxy() {...})
change it to
app.use(URL, proxy() {...})
app.use(bodyParser(...))
@mahyarmobilab Thanks, wrapping proxy and calculating dynamically parseReqBody
works
I took @btmurrell's code which was a modified version of @mahyarmobilab's and added further changes that I find simpler, although all three of these solutions should be effective. I am running express-http-proxy v1.5.1 and this works for me.
- I changed
proxyMiddleware
so that is no longer a thunk. (A thunk is a function that takes no input and just returns a value for the purpose of delaying its execution-- however in the code above it gets executed immediately right below, so I don't think it added anything in this case.) - I removed
reqBodyEncoding
andreqAsBuffer
since, per the documentation ofparseReqBody
, those values are ignored whenparseReqBody
is set to false.
const isMultipartRequest = (req) => {
const contentTypeHeader = req.headers["content-type"];
return contentTypeHeader && contentTypeHeader.indexOf("multipart") > -1;
};
const proxyMiddleware = (req, res, next) => {
return proxy(targetHost, {
parseReqBody: !isMultipartRequest(req),
// your other fields here...
})(req, res, next);
};
app.use(path, proxyMiddleware);
Thanks @mahyarmblb, your solution is working splendidly four years down the line. Also keeps the code clean :)
@20matan 's solution worked for me, if you are just proxying the requests just move down the express.json() / bodyParser.json()