This is the sample proxy.jsp file for the the VideoManager application. It proxies the request to the API interface and its response. In a production deployment, you would make sure this page was not accessible to the outside. Read more about how this sample application works.
<%@page import = "org.apache.commons.httpclient.*,
org.apache.commons.fileupload.FileItem,
org.apache.commons.fileupload.servlet.ServletFileUpload,
org.apache.commons.fileupload.FileItemStream,
org.apache.commons.fileupload.FileItemIterator,
org.apache.commons.fileupload.util.Streams,
java.io.InputStream,
java.util.List,
java.util.Arrays,
java.io.File,
java.io.FileOutputStream,
java.util.Enumeration,
org.apache.commons.httpclient.methods.PostMethod,
org.apache.commons.httpclient.methods.GetMethod,
org.apache.commons.httpclient.methods.multipart.Part,
org.apache.commons.httpclient.methods.multipart.StringPart,
org.apache.commons.httpclient.methods.multipart.FilePart,
org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity" %>
<%
/****************************************************************
* proxy.jsp -- Media API Proxy
* Takes requests sent by client and forwards it to external API server
* to avoid cross-domain scripting issues.
* Also forwards tokens to keep them hidden.
*****************************************************************//*****************************************************************
*Media API Strings go Here
* -Fill in with your info
* *Make sure you include the '.' at the end of the token*
******************************************************************/
final String apiReadLoc = "http://services-godzilla.qanet.local/services/library";
//final String apiReadLoc = "http://localhost:8080/services/library";
final String apiWriteLoc = "http://services-godzilla.qanet.local/services/post";
//final String apiWriteLoc = "http://localhost:8080/services/post";
final String apiReadToken = "lKExdbIcuyKLoqJM2NOatvxPThsb5BEpZWF3yNuIfbU.";
//final String apiReadToken = "riBfgveLvpQ5OS4_D9jZxXushEmUmH9WoT4dBuEskrU.";//localhost
final String apiWriteToken = "sHXE01ncrhhw1FEmvn82vIJ_UXDVYxXT-1X9strHvKM.";
//final String apiWriteToken = "riBfgveLvpRb-rHAkx3mBISAQXs-Q8NmphGxt0z04kE.";//localhost
/*************************************************************
*Don't do any error checking for paramters here, just forward them along
* since the api server will check them anyway.
**************************************************************/
/*******************************************************************************
*This list contains the names of all the write methods. It's used to check to see if a command
* sent as a GET request should be forwarded as a multipart/post request.
********************************************************************************/g
final List <String> write_methods = Arrays.asList(
new String[] {"create_video", "update_video", "delete_video",
"get_upload_status", "create_playlist", "update_playlist", "share_video"}
);
/**************************************************************************
* (*) bar is the all purpose utility string. For write requests it's used to construct and
* hold the formatted JSON request. For read requests it's used to construct and
* hold the request URL.
*
*(*) useGet is to determine whether the request should be sent as a GET or POST request,
* since some requests that should be sent as a POST arrive as a GET.
***************************************************************************/
String bar = null;
boolean useGet = false;
try{
if(request.getMethod() == "POST"){
useGet = false;
boolean createFile = false;
bar = "{";
String command = new String();
String params = new String();
/*********************************************************************************
* This section uses the httpclient and fileupload packages from the apache commons
* to send a multipart post request. First the fileupload class is used to parse
* the received form data and construct a JSON request. If there is a file part,
* it's content is streamed to a temporary file and then sent to the api server in once piece.
* The FileItemIterator iter traverses through the parts of the POST request.
* It looks for certain field names to construct the JSON object for different types of requests.
* video and playlist objects are passed from the client as whole objects.
* data is passed from share_video.
*
* The Streaming API from fileUpload is used as it offers faster performance.
* However, since an uploaded file could be too large to stream and dynamically allocate
* all uploaded files are written to a temp file first. This is potentially slower for smaller files, but
* required for larger ones. Since the streaming API is faster in most situations, for most files
* this setup should be faster than using the traditional fileUpload API. The traditional fileUpload
* API does allow you to check the size of an uploaded file before processing it (since it's not a stream)
* so if you plan on uploading many smaller files, that might be a more efficient solution.
***********************************************************************************/
ServletFileUpload upload = new ServletFileUpload();
FileItemIterator iter = upload.getItemIterator(request);
InputStream fileStream;
File tempFile = null;
while(iter.hasNext() ){
FileItemStream item = iter.next();
String fieldName = item.getFieldName();
if(!item.isFormField()){//isFormField returns false if the item is a file
createFile = true;
fileStream = item.openStream();
//On a Unix-like operating system "/tmp/" should be
//appended before the file name when creating the tempfile.
//tempFile = new File("/tmp/"+item.getName());
tempFile = new File(item.getName());
tempFile.deleteOnExit();
FileOutputStream outStream = new FileOutputStream(tempFile);
byte [] buf = new byte [1024];
for(int byLen = 0; (byLen = fileStream.read(buf, 0, 1024)) > 0;){
outStream.write(buf, 0, byLen);
//if(tempFile.length()/1000 > 2){}//maximum file size is 2gigs
}
outStream.close();
}else if( fieldName.equals("video")){
params = "\"video\": " + Streams.asString(item.openStream());
}else if( fieldName.equals("data")){
params = Streams.asString(item.openStream());
}else if( fieldName.equals("playlist")){
params = "\"playlist\": " + Streams.asString(item.openStream());
}else if( fieldName.equals("command")){
command = Streams.asString(item.openStream());
}else if( fieldName.equals("callback")){
bar += " \"callback\": \"" + Streams.asString(item.openStream()) + "\",";
}
}
bar += "\"method\": \""+command+"\", \"params\": {";
bar += params;
bar += ",\"token\": \""+apiWriteToken+"\"}}";
/************************************************
* Uncomment this line to print out the JSON request.
* Useful for debugging, remove the style from
* postFrame in default.html or capture it in charles
* to view the output.
************************************************/
//out.print(bar);
/********************************************************
* This section constructs the multipart request using the
* httpclient package from the apache commons.
* The StringPart holds bar, which is a utility string used
* to construct and hold the formatted JSON request.
* If a file was uploaded, a FilePart object is created that contains
* the uploaded file.
**********************************************************/
Part[] parts;
if(createFile){
parts = new Part[2];
//JSON request always comes before the file part.
parts[0] = new StringPart("JSON-RPC", bar);
parts[1] = new FilePart("file", tempFile);
}else{
parts = new Part[1];
parts[0] = new StringPart("JSON-RPC", bar);
}
HttpClient client = new HttpClient();
PostMethod postreq = new PostMethod(apiWriteLoc);
postreq.setRequestEntity( new MultipartRequestEntity(parts, postreq.getParams()) );
client.executeMethod(postreq); //Actually execute the request.
/***********************************************************
*This checks for an error in the actual transmission, not in
* the Media API command. Even if the status code is SC_OK
* there could've been a problem with the formatting of the request
* or it didn't execute correctly. This only indicates the data was sent
* and received ok.
************************************************************/
if(postreq.getStatusCode() == HttpStatus.SC_OK){
out.print(postreq.getResponseBodyAsString());
postreq.releaseConnection();
}else{
out.print( "Post Failed, error: " + postreq.getStatusLine());
postreq.releaseConnection();
}
/**************************************************************************
*Some write methods (like delete_video) are sent as GET requests, which is simpler,
* especially if there are only a few fields of data to send.
* Check to see if the method of the GET request is a write command, and if it is,
* construct a JSON request and send it as a multipart/field data POST request.
***************************************************************************/
}else if ( write_methods.contains(request.getParameter("command")) && request.getMethod() == "GET"){
useGet = false;
String temp;
//The method can't be part of the params section, so we write that out first, then the token and then loop through the rest of the parameters.
bar = "{\"method\": \"" + request.getParameter("command") + "\", \"params\": {\"token\": \"" + apiWriteToken +"\"";
for(Enumeration e = request.getParameterNames(); e.hasMoreElements();){
temp = (String) e.nextElement();
//don't want to include command twice
if(!temp.equals("command")){
bar += ",\""+temp+"\": \"" +request.getParameter(temp)+"\"";
}
}
bar += "}}";
//out.print(bar);
Part[] parts = {new StringPart("data", bar)};
HttpClient client = new HttpClient();
PostMethod postreq = new PostMethod(apiWriteLoc);
postreq.setRequestEntity( new MultipartRequestEntity(parts, postreq.getParams()) );
client.executeMethod(postreq);
if(postreq.getStatusCode() == HttpStatus.SC_OK){
out.print(postreq.getResponseBodyAsString());
postreq.releaseConnection();
}else{
out.print( "Post Failed, error: " + postreq.getStatusLine());
postreq.releaseConnection();
}
/******************************************************************************
* The last case is an incoming GET request that should be forwarded as a GET request.
* We set useGet to true and concatenate the read token at the end of the parameter string.
* The JSTL below sends the entire request and sends the response from the API server
* back to the client.
*******************************************************************************/
}else{
useGet = true;
bar = apiReadLoc + '?' + request.getQueryString() + "&token=" + apiReadToken;
/************************************************************************************
*If you don't want to support JSTL, the block below duplicates the functionality of the JSTL block
*at the bottom of this document. It might be faster to use JSTL but this hasn't been verified.
*************************************************************************************/
/*HttpClient client = new HttpClient();
HttpMethod getreq = new GetMethod(bar);
client.executeMethod(getreq);
if(getreq.getStatusCode() == HttpStatus.SC_OK){
out.print(getreq.getResponseBodyAsString());
getreq.releaseConnection();
}else{
out.print( "Get Failed, error: " + getreq.getStatusLine());
getreq.releaseConnection();
}*/
}
}catch(Exception e){
out.write("{\"error\": \"Proxy Error, please check your tomcat logs.\", \"result\":null, \"id\": null}");
}%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:if test="<%=useGet%>" >
<c:import url="<%=bar%>" />
</c:if>