Skip to content

Instantly share code, notes, and snippets.

@rtconner
Last active May 2, 2016 16:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rtconner/f8a7cab3e00aada18996c3b5422d7b30 to your computer and use it in GitHub Desktop.
Save rtconner/f8a7cab3e00aada18996c3b5422d7b30 to your computer and use it in GitHub Desktop.
Salesoforce Apex parse RestRequest into multipart
public with sharing class RestRequestMultipart
{
public List<RestRequest> requests;
public Map<String, String> headers;
public String httpMethod;
public Map<String, String> params;
public String remoteAddress;
public String requestURI;
public String resourcePath;
private RestRequest originalRequest;
public RestRequestMultipart(RestRequest req)
{
this.setAttributes(req);
this.buildRequestList(req);
}
/**
* Parse original request into its mutliparts
*/
private void buildRequestList(RestRequest req)
{
this.requests = new List<RestRequest>();
String boundary = req.headers.get('boundary');
List<String> parts = req.requestBody.toString().split('--'+boundary);
for(String part : parts) {
if(part.length() == 0) {
continue;
}
Integer splitter = part.indexOf('\n\n');
String headersString = part.substring(0, splitter);
String body = part.substring(splitter+2, part.length()-1);
RestRequest newRequest = new RestRequest();
Map<String, String> headerMap = this.buildHeaders(headersString);
for(String key : headerMap.keySet()) {
newRequest.addHeader(key, headerMap.get(key));
}
newRequest.requestBody = Blob.valueOf(body);
this.requests.add(newRequest);
}
}
@TestVisible
private Map<String, String> buildHeaders(String headerString)
{
Map<String, String> headerMap = new Map<String, String>();
List<String> headerList = headerString.split('\n');
for(String headerLine : headerList) {
if(headerLine.length() == 0) {
continue;
}
Integer colon = headerLine.indexOf(':');
headerMap.put(
headerLine.substring(0, colon).trim(),
headerLine.substring(colon+1).trim()
);
}
return headerMap;
}
private void setAttributes(RestRequest req)
{
this.originalRequest = req;
this.headers = req.headers;
this.httpMethod = req.httpMethod;
this.params = req.params;
this.remoteAddress = req.remoteAddress;
this.requestURI = req.requestURI;
this.resourcePath = req.resourcePath;
}
}
@isTest
public with sharing class RestRequestMultipartTest
{
@isTest
public static void test_parsing_mutlipart_request()
{
String body = '--83ff53821b7c' +'\n'+
'Content-Disposition: form-data; name="img"; filename="a.png"' +'\n'+
'Content-Type: application/octet-stream' +'\n'+
+'\n'+
'testcontent1\n'+
'--83ff53821b7c' +'\n'+
'Content-Disposition: form-data; name="foo"' +'\n'+
+'\n'+
'testcontent2' +'\n'+
'--83ff53821b7c';
RestRequest req = new RestRequest();
req.addHeader('boundary', '83ff53821b7c');
req.requestBody = Blob.valueOf(body);
RestRequestMultipart multipart = new RestRequestMultipart(req);
System.assertEquals(2, multipart.requests.size());
System.assertEquals('testcontent2', multipart.requests.get(1).requestBody.toString());
}
@isTest
public static void test_header_builder()
{
RestRequest req = new RestRequest();
req.requestBody = Blob.valueOf('');
RestRequestMultipart multipart = new RestRequestMultipart(req);
String headString =
'Content-Disposition: form-data; name="img"; filename="a.png"' +'\n'+
'Content-Type: application/octet-stream' +'\n' +
'Some : thing\n' +
'Content-Length:22'
;
Map<String, String> headers = multipart.buildHeaders(headString);
System.assertEquals(headers.get('Content-Length'), '22');
System.assertEquals(headers.get('Some'), 'thing');
System.assertEquals(4, headers.size());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment