Reverse Proxy Not working for Angular App - javascript

Hi I'm trying to open hosted angular app to my application without using iFrame , Object and embed tags. Below is my Handler code. Css and js files are loaded properly but site is not working as expected.
**web.config app settings:**
<add key="ProxyMode" value="1"/>
<add key="RemoteWebSite" value="http://localhost/angulartest"/>
**Handler :**
public class ReverseProxy : IHttpHandler
{
private static string GetContentType(string url)
{
if (url.ToLower().Contains(".css"))
{
return "text/css";
}
else if (url.ToLower().Contains(".js"))
{
return "application/javascript";
}
else
{
return "text/html";
}
}
/// <summary>
/// Method calls when client request the server
/// </summary>
/// <param name="context">HTTP context for client</param>
public void ProcessRequest(HttpContext context)
{
//read values from configuration file
int proxyMode = Convert.ToInt32(ConfigurationSettings.AppSettings["ProxyMode"]);
string remoteWebSite = ConfigurationSettings.AppSettings["RemoteWebSite"];
string remoteUrl;
if (proxyMode == 0)
remoteUrl = ParseURL(context.Request.Url.AbsoluteUri); //all site accepted
else
remoteUrl = context.Request.Url.AbsoluteUri.Replace("http://" + context.Request.Url.Host + context.Request.ApplicationPath, remoteWebSite); //only one site accepted
//create the web request to get the remote stream
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(remoteUrl);
//TODO : you can add your own credentials system
//request.Credentials = CredentialCache.DefaultCredentials;
HttpWebResponse response;
try
{
response = (HttpWebResponse)request.GetResponse();
}
catch (System.Net.WebException ex)
{
string dsdl;
using (var sr = new StreamReader(ex.Response.GetResponseStream()))
dsdl = sr.ReadToEnd();
//remote url not found, send 404 to client
context.Response.StatusCode = 404;
context.Response.StatusDescription = "Not Found";
context.Response.Write(dsdl);
context.Response.End();
return;
}
Stream receiveStream = response.GetResponseStream();
context.Response.ContentType = GetContentType(remoteUrl);
StreamReader readStream = new StreamReader(receiveStream, Encoding.Default);
Uri test = new Uri(remoteUrl);
string content;
if (proxyMode == 0)
content = ParseHtmlResponse(readStream.ReadToEnd(), context.Request.ApplicationPath + "/http//" + test.Host);
else
content = ParseHtmlResponse(readStream.ReadToEnd(), context.Request.ApplicationPath);
//write the updated HTML to the client
context.Response.Write(content);
//close streams
readStream.Close();
response.Close();
context.Response.End();
}
/// <summary>
/// Get the remote URL to call
/// </summary>
/// <param name="url">URL get by client</param>
/// <returns>Remote URL to return to the client</returns>
public string ParseURL(string url)
{
if (url.IndexOf("http/") >= 0)
{
string externalUrl = url.Substring(url.IndexOf("http/"));
return externalUrl.Replace("http/", "http://");
}
else
return url;
}
/// <summary>
/// Parse HTML response for update links and images sources
/// </summary>
/// <param name="html">HTML response</param>
/// <param name="appPath">Path of application for replacement</param>
/// <returns>HTML updated</returns>
public string ParseHtmlResponse(string html, string appPath)
{
html = html.Replace("\"/", "\"" + appPath + "/");
html = html.Replace("'/", "'" + appPath + "/");
html = html.Replace("=/", "=" + appPath + "/");
return html;
}
///
/// Specifies whether this instance is reusable by other Http requests
///
public bool IsReusable
{
get
{
return true;
}
}
}
Controller HTML is not firing. Attached Fiddler response also.
angulartest => Hosted angular application
ReverseProxy => My own application
Inbox.html not firing in my ReverseProxy project..
Please help me for this.

Finally I found the answer. Hosted application angular js relative path not taking during Reverse Proxy. So I added in CDN version of angular js in index.html,
Now it's working perfectly.

Related

Download file in Webview

I'm using webview in an Android application. I am trying to download a .pdf file, however when the link is clicked through the application the .pdf file name is changed to "1rcPnhg9_rSes92BiQPotVjXuEAfFnyrf.pdf", and is not saved with the original file name.
How to make webview save the file with the original name? At the moment the webview is saving the file using the ID as the name.
Used link: https://drive.google.com/uc?export=download&id=1rcPnhg9_rSes92BiQPotVjXuEAfFnyrf
WebView:
webView.setDownloadListener(new DownloadListener()
{
#Override
public void onDownloadStart(String url, String userAgent,
String contentDisposition, String mimeType,
long contentLength) {
DownloadManager.Request request = new DownloadManager.Request(
Uri.parse(url));
request.setMimeType(mimeType);
String cookies = CookieManager.getInstance().getCookie(url);
request.addRequestHeader("cookie", cookies);
request.addRequestHeader("User-Agent", userAgent);
request.setDescription("Downloading File...");
request.setTitle(URLUtil.guessFileName(url, contentDisposition, mimeType));
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
request.setDestinationInExternalPublicDir(
Environment.DIRECTORY_DOWNLOADS, URLUtil.guessFileName(
url, contentDisposition, mimeType));
DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
dm.enqueue(request);
Toast.makeText(getApplicationContext(), "Downloading File", Toast.LENGTH_LONG).show();
}});
Permissions in Manifest:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />
<uses-permission android:name="android.permission.ACCESS_DOWNLOAD_MANAGER"/>
Here a test with your link (in Kotlin). If you need a Java example, please, let me know:
private fun test() {
webView = findViewById(R.id.webView)
webView.webViewClient = object : WebViewClient() {
override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
Log.d(TAG, "shouldOverrideUrlLoading:url = ${url}")
if (url.contains("=download")){
Log.d(TAG, "shouldOverrideUrlLoading: ")
downloadFile(url)
webView.stopLoading()
}
return true
}
}
val url = "https://drive.google.com/uc?export=download&id=1rcPnhg9_rSes92BiQPotVjXuEAfFnyrf"
webView.loadUrl(url)
}
fun downloadFile(url: String) {
Log.d(TAG, "downloadFile: url = $url")
val manager = getSystemService(Activity.DOWNLOAD_SERVICE) as DownloadManager
val uri =
Uri.parse(url)
val request = DownloadManager.Request(uri)
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
val reference: Long = manager.enqueue(request)
}
image abuot download
Java code:
private void test() {
webView = findViewById(R.id.webView);
webView.setWebViewClient(new WebViewClient(){
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if(url.contains("=download")){
downloadFile(url);
}
return super.shouldOverrideUrlLoading(view, url);
}
});
String url = "https://drive.google.com/uc?export=download&id=1rcPnhg9_rSes92BiQPotVjXuEAfFnyrf";
webView.loadUrl(url);
}
private void downloadFile(String url) {
DownloadManager manager = (DownloadManager) getSystemService(Activity.DOWNLOAD_SERVICE);
Uri uri = Uri.parse(url);
DownloadManager.Request request = new DownloadManager.Request(uri);
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
manager.enqueue(request);
}
An option to use DownloadManager
For this you sould add an onNavigating event to your WebView. If the user target a pdf file you can stop the loading process with: ags.Cancel = true
And this point when you can pass the url to a DownloadManager what will download your file.
Here a simple code
webView.webViewClient = object : WebViewClient() {
override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
if (url.contains(".pdf")){
downloadFile(url)
}
return false
}
}
fun downloadFile(url: String) {
Log.d(TAG, "downloadFile: url = $url")
val manager = getSystemService(Activity.DOWNLOAD_SERVICE) as DownloadManager
val uri =
Uri.parse(url)
val request = DownloadManager.Request(uri)
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
val reference: Long = manager.enqueue(request)
}

File Downloading in Struts 2 won't start

I've the following struts code. I'm trying to download a csv file but nothing happens when I click download. I don't get any errors and in javascript I get a successful response. Myy post function logs my csv content on browser console too. I can't see why the file download won't start downloading.
Here is my jsp:
<%# taglib prefix="s" uri="/struts-tags"%>
<div>
<div>
<h4>Information</h4>
<div class="tab-pane" id="login">
<div class="panel panel-default">
<form id = "info" class="form-horizontal">
<div >
<label>FName</label>
<span style="float:right"><s:property value="%{fName}"
</span>
</div>
<div>
<label>MName or Initial</label>
<span style="float:right"><s:property value="%{mName}"/></span>
</div>
<div>
<label>LName</label>
<span style="float:right"><s:property value="%{lName}"/></span>
</div>
</form>
</div>
</div>
</div>
<div class="footer">
<button type="button" class="btn btn-primary" onClick="download();">Download</button>
</div>
</div>
<script>
function download(){
var action = 'download.action';
var meth = 'post';
var fields = jQuery("#info").children();
var params = [];
for(var i=0; i<fields.length;i++){
var field = fields[i];
var nodes = jQuery(field).children();
if(nodes.length == 2){
params.push(encodeURIComponent(nodes[0].innerText)
+"="+
encodeURIComponent(nodes[1].innerText));
}
}
var encr = btoa(params.join('&'));
jQuery.post(action,"data="+encr,function(data,status,xhr){
console.log(data);
console.log(status);
console.log(xhr);
});
}
</script>
Action class
public class Downloads extends CustomActionClass{
private static final long serialVersionUID = 1L;
private String data;
private InputStream fileStream;
private long contentLength;
public String execute() {
String decodeData = new
String(java.util.Base64.getDecoder().decode(data));
List<String> downloadData = new ArrayList<String>();
try {
String fileName = "info.csv";
String [] dataList = URLDecoder.decode(decodeData,"UTF-8").split("&");
String header ="";
String vals = "";
for(String dat: dataList) {
String[] tData = dat.split("=");
header += tData[0] + ",";
if(tData.length>1)
vals += tData[1]+",";
}
if(StringUtils.isNotBlank(header))
downloadData.add(header.substring(0,header.length()-1));
if(StringUtils.isNotBlank(vals))
downloadData.add(vals.substring(0,vals.length()-1));
File fil = new File(getServerTempFolder()+fileName);
fil.createNewFile();
contentLength = fil.length();
FileUtils.writeLines(fil, "UTF-8", downloadData);
fileStream = new FileInputStream(fil);
} catch (Exception e) {
log.info("Error: " + e.getMessage());
log.debug(e.fillInStackTrace());
}
return SUCCESS;
}
/**
* #return the data
*/
public String getData() {
return data;
}
/**
* #param data the data to set
*/
public void setData(String data) {
this.data = data;
}
/**
* #return the fileStream
*/
public InputStream getFileStream() {
return fileStream;
}
/**
* #param fileStream the fileStream to set
*/
public void setFileStream(InputStream fileStream) {
this.fileStream = fileStream;
}
/**
* #return the contentLength
*/
public long getContentLength() {
return contentLength;
}
/**
* #param contentLength the contentLength to set
*/
public void setContentLength(long contentLength) {
this.contentLength = contentLength;
}
}
Here is my Struts Mapping:
<action name="download" class="com.util.Downloads">
<result name="success" type="stream">
<param name="contentType">application/octet-stream</param>
<param name="contentLength">${contentLength}</param>
<param name="inputName">fileStream</param>
<param name="contentDisposition">attachment;filename="info.csv"</param>
<param name="bufferSize">1024</param>
I have solved this issue. So the solution to this is that ajax call won't trigger the download since it's a post request. I had to do window.href=action; this made the get call and hence the stream was returned from the action class.
I'm going to go one step further in case anyone has encoding issues. To encode properly for pdf write correct headers to specify UTF-8 encoding.. for csv write this to file byte[] enc = new byte[] { (byte)0xEF, (byte)0xBB, (byte)0xBF }; before you start write your data to file. And yes you can write this byte stream and then write String data to file.
Refer to this link for CSV http://smallbusiness.chron.com/utf8-encoding-excel-using-java-47939.html ...

Access android assets folder using javascript file

I am injecting a javascript file to the WebView and that javascript file needs to load more files from the app assets folder.
i used to load the files from remote server, but now i need to load them locally.
I am getting "not allowed to load local resource".
is this even possible? i can't find any solution here or using google.
example:
...
webView.loadUrl("javascript:(function() {" +
"var parent = document.getElementsByTagName('head').item(0);" +
"var script = document.createElement('script');" +
"script.type = 'text/javascript';" +
"script.innerHTML = window.atob('" + encoded + "');" +
"parent.appendChild(script)" +
"})()");
this injects a "script.js" file into the webview.
inside the script.js file i want to inject css background image that is located inside the app assets folder. when im trying to access "file:///android_asset" i get the "not allowed to load local resource" error.
if you want load your local html page and resources to the web view you should use webView.loadDataWithBaseURL
public void loadLocalHtmlToWebView() throws IOException {
WebView mWebView = findViewById(R.id.my_webview);
File publicDir = new File(getCacheDir(), "public");
if (publicDir.exists() == false) {
publicDir.mkdirs();
String[] ls = getAssets().list("public");
for (int i = 0; i < ls.length; i++) {
InputStream inputStream = getAssets().open("public/" + ls[i]);
File outFileLocation = new File(publicDir, ls[i]);
outFileLocation.createNewFile();
Log.e("AMIR", "Wrinting to : " + outFileLocation.getPath());
FileOutputStream fileOutputStream = new FileOutputStream(outFileLocation);
byte[] buffer = new byte[1024];
while (inputStream.read(buffer) != -1) {
fileOutputStream.write(buffer);
}
fileOutputStream.flush();
fileOutputStream.close();
inputStream.close();
}
}
String indexHtml="";
BufferedReader bufferedReader=new BufferedReader(new FileReader(new File(publicDir,"index.html")));
String ln="";
while((ln=bufferedReader.readLine())!=null){
indexHtml+=ln;
}
bufferedReader.close();
Log.e("AMIR","Html : "+indexHtml);
String baseUrl = "file://" + publicDir.getPath() + "/";
mWebView.loadDataWithBaseURL(baseUrl, indexHtml, "text/html", "UTF-8", null);
}
Assets folder :
my index.html code :
<html>
<head>
<title>Hello</title>
<head>
<body>
Hello
<img src="./img.jpg"/>
<body>
</html>
and this is a good and well explained tutorial for webView :
http://tutorials.jenkov.com/android/android-web-apps-using-android-webview.html

how to configure ajax site for googlebot?

I have an angular site that I have enabled html5 mode so I can have pretty urls. I need to configure the site for googlebot. What I have done so far is put this in the meta tag:
<meta name="fragment" content="!">
My assumption is by placing that meta tag, I am informing googlebot that it is an ajax site and that it should append _escaped_fragment_ in the url right inbetween domain name and the rest of the of url. For example, if it was trying to crawl http://thehaileselassie.com/Italian_Occupation, it would transform it to http:// thehaileselassie.com/?_escaped_fragment_=Italian_Occupation. But I don't think that is what is happening. I believe it is appending it to the end, like so: http:// thehaileselassie.com/Italian_Occupation?_escaped_fragment_=. I am not quite sure what I am doing wrong.
Extra info
I have this in RouteConfig so all server calls are sent to HomeController:
routes.MapRoute(
name: "Default",
url: "{*url}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
And this is the content of the controller:
public ActionResult Index()
{
string fragment = Request.QueryString["_escaped_fragment_"];
if (fragment != null)
{
if (String.IsNullOrWhiteSpace(fragment))
{
string url = "/templates/homeView.html";
return File(Server.MapPath(url), "text/html");
}
else
{
string url = "/templates/" + fragment + ".html";
return File(Server.MapPath(url), "text/html");
}
}
return View();
}
?_escaped_fragment_= is supposed to be appended to end. What I am doing to get the part after the domain is this: Request.Url.LocalPath. This returns /Italian_Occupation. Afterwards I do some logic to create xml on the fly and return it:
string url = "/templates" + Request.Url.LocalPath + ".html";
XmlDocument doc = new XmlDocument();
try
{
doc.Load(Server.MapPath(url));
}
catch
{
return HttpNotFound();
}
var settings = new System.Xml.XmlWriterSettings();
var propInfo = settings.GetType().GetProperty("OutputMethod");
propInfo.SetValue(settings, System.Xml.XmlOutputMethod.Html, null);
var stream = new System.IO.StringWriter();
var writer = System.Xml.XmlWriter.Create(stream, settings);
// XmlElement elem = doc.CreateElement("book", "aaaa", "http://www.com");
//// doc.DocumentElement.AppendChild(elem);
// doc.DocumentElement.(elem, doc.DocumentElement.LastChild);
XmlDocument doc2 = new XmlDocument();
XmlElement element1 = doc2.CreateElement(string.Empty, "html", string.Empty);
doc2.AppendChild(element1);
XmlElement element2 = doc2.CreateElement(string.Empty, "head", string.Empty);
XmlElement element4 = doc2.CreateElement(string.Empty, "title", string.Empty);
XmlText text1 = doc2.CreateTextNode("TheHaileSelassie.Com :: "+doc.GetElementsByTagName("h1")[0].InnerText);
element4.AppendChild(text1);
element2.AppendChild(element4);
doc2.DocumentElement.AppendChild(element2);
XmlElement element3 = doc2.CreateElement(string.Empty, "body", string.Empty);
XmlDocumentFragment xfrag = doc2.CreateDocumentFragment();
xfrag.InnerXml = doc.InnerXml;
element3.AppendChild(xfrag);
doc2.DocumentElement.AppendChild(element3);
//doc2.DocumentElement.AppendChild(xfrag);
doc2.Save(writer);
return Content(System.Net.WebUtility.HtmlDecode(stream.ToString()));

Trying to upload a file using ajax in ASP.NET MVC

I am using ASP.NET MVC 3, I want to upload a image file using an ajax form
My Index view code is:
<% using (Ajax.BeginForm("Save","Home", new AjaxOptions() { HttpMethod = "POST", InsertionMode = InsertionMode.Replace }, new { enctype = "multipart/form-data" }))
{%>
<input type="file" /><input type ="submit" value="Submit File"/>
<% } %>
and Controller code is:
[HttpPost]
public ActionResult Save()
{
ViewBag.Message = "Welcome to ASP.NET MVC!";
return View("Index");
}
When I upload a file and click on the button, the ajax form is submitted, but i am getting a Request.File.Count of 0.
Default unobtrusive ajax in mvc doesn't support uploading files. You need to use hidden iframe/plugin (flash, silverlight..)/html5 or combination of those.
Some scripts that might help you:
http://valums.com/ajax-upload/
http://www.uploadify.com/
You can use the the plugins suggested by #Lukáš Novotný or else you can do the following
Create an Generic HTTP handler uploadfile.ashx
Post the data to the file(set the form action="yourpath/UploadFile.ashx"
In the handler you can read the file as
HttpPostedFile uploadedfile = context.Request.Files[0];
Here's my Action that manages the file uploads. Would work with most Ajaxy file uploaders. (I think)
public ActionResult Upload(HttpPostedFileBase uploadfile)
{
try
{
var dr405 = new DR405Service().GetDR405ById(new DR405DBContext(), DR405Profile.CurrentUser.TangiblePropertyId);
var saveLocation = Path.Combine(DR405Service.SavePath + DR405Profile.CurrentUser.TangiblePropertyId);
System.IO.Directory.CreateDirectory(saveLocation);
if ((int)uploadfile.ContentLength / 1024 <= 15000)
{
uploadfile.SaveAs(Path.Combine(saveLocation, Path.GetFileName(uploadfile.FileName)));
var file = new dr405files { TangiblePropertyId = DR405Profile.CurrentUser.TangiblePropertyId, FileName = uploadfile.FileName, UploadDate = DateTime.Now };
//dr405.dr405files.Add(file);
//c.dr405s.Add(dr405);
db.Entry(file).State = file.FileId == 0 ? EntityState.Added : EntityState.Modified;
//db.Entry(dr405).State = EntityState.Modified;
new DR405Service().Save(db);
ViewData["UploadStatus"] = String.Format("File name: {0}, {1}Kb Uploaded Successfully.", uploadfile.FileName, (int)uploadfile.ContentLength / 1024);
}
else
{
ViewData["UploadStatus"] = String.Format("File exceeds 15MB upload limit. Please reduce size and try again.", uploadfile.FileName);
}
}
catch (Exception ex)
{
ViewData.ModelState.AddModelError("_FORM", ex.ToString());
}
return View();
}

Categories