Encoded slash (%2F) in query parameter causes redirection to fail in Angular Application - angularjs

In my angular application, I need to make GET call to a Tomcat server. This GET call requires query parameters which could contain special characters too like "+", "/", "/+"
GET call is being made from angular controller using $window.open with target as "_blank"
Currently the redirection is getting failed without any encoding.
So, I added encoding in .js file before the GET call is being made by using encodeURIComponent.
Then I added decoding logic using URLDecode.decode in backend java code to decode query parameters.
But still it doesn't work.
It works only if I encode query parameters twice within the .js file using encodeURIComponent twice.
I am trying to find the root cause for double encoding but no luck yet. I would greatly appreciate if anyone could share any inputs.

Made it work by adding a * in path parameter in app.js. Adding a star means that the request will include multiple path parameters separated by /, and so angular will not try to encode / in the request.
Double encoding could also work but then the server side logic has to be modified to decode the request parameters twice and replace %2B2F by %2F

Related

Apache Camel Interceptor with regular expression

This is my route. I want to send a file to an Azure blob. I want to set the name of the blob as the file name without extension. I also want to filter out the whitespaces from the file names. I am thinking of using an interceptor
from("file://C:/camel/source1").recipientList(simple("azure-blob://datastorage/container1/${header.fileName}?credentials=#credentials&operation=updateBlockBlob"))
I want to invoke the interceptor only for updateBlockBlob operatin
interceptSendToEndpoint("^(azure-blob:).+(operation=updateBlockBlob)").setHeader("fileName",simple("${file:onlyname.noext}")).convertBodyTo(File.class)
The above code works with interceptFrom().
I tried replacing the regular expression with wild card like azure* i.e interceptSendToEndpoint("azure*"). It did not work
Whats wrong with the above code? Is it because of recipientList?
Also what features does simple have to remove white space?
Is there a better way to generate blob names dynamically?
Here is the documentation from camel on interceptors.
http://camel.apache.org/intercept.html
interceptFrom that intercepts incoming Exchange in the route.
interceptSendToEndpoint that intercepts when an Exchange is about to
be sent to the given Endpoint.
So I suspect the Exchange is already formed and camel expects the url to be resolved.
So the header needs to be set before the exchange is created for the Azure end point.
I did the following. To set the header, I use the interceptFrom, and to convert the object into File I used the inteceptSendToEndPoint
interceptSendToEndpoint("^(azure-blob:).+(operation=updateBlockBlob)").convertBodyTo(File.class)
interceptFrom().setHeader("fileName",simple("${file:onlyname.noext}".replaceAll("[^a-zA-Z\d]")))
Managed to get rid of the whitespace too

AngularJS $http service has CORS issue. But it should be working for JSONP, right? [duplicate]

I'm trying to load an external page using JSONP, but the page is an HTML page, I just want to grab the contents of it using ajax.
EDIT: The reason why I'm doing this is because I want to pass all the user information ex: headers, ip, agent, when loading the page rather than my servers.
Is this doable? Right now, I can get the page, but jsonp attempts to parse the json, returning an error: Uncaught SyntaxError: Unexpected token <
Sample code:
$.post('http://example.com',function(data){
$('.results').html(data);
},'jsonp');
I've set up a jsfiddle for people to test with:
http://jsfiddle.net/8A63A/1/
http://en.wikipedia.org/wiki/JSONP#Script_element_injection
Making a JSONP call (in other words, to employ this usage pattern),
requires a script element. Therefore, for each new JSONP request, the
browser must add (or reuse) a new element—in other words,
inject the element—into the HTML DOM, with the desired value for the
"src" attribute. This element is then evaluated, the src URL is
retrieved, and the response JSON is evaluated.
Now look at your error:
Uncaught SyntaxError: Unexpected token <
< is the first character of any html tag, probably this is the start of <DOCTYPE, in this case, which is, of course, invalid JavaScript.
And NO, you can't use JSONP for fetching html data.
I have done what you want but in my case I have control of the server side code that returns the HTML.
So, what I did was wrapped the HTML code in one of the Json properties of the returned object and used it at client side, something like:
callback({"page": "<html>...</html>"})
The Syntax error you are facing it's because the library you're using expects json but the response is HTML, just that.
I've got three words for you: Same Origin Policy
Unless the remote URL actually supports proper JSONP requests, you won't be able to do what you're trying to. And that's a good thing.
Edit: You could of course try to proxy the request through your server …
If you really just want to employ the client to snag an HTML file, I suggest using flyJSONP - which uses YQL.. or use jankyPOST which uses some sweet techniques:
jankyPOST creates a hidden iframe and stuffs it with a form (iframe[0].contentWindow.document.body.form.name).
Then it uses HTML5 (watch legacy browsers!) webMessaging API to post to the other iframe and sets iframe's form elements' vals to what u specified.
Submits form to remote server...done.
Or you could just use PHP curl, parse it, echo it, so on.
IDK if what exactly ur using it for but I hope this helps.
ALSO...
I'm pretty sure you can JSONP anything that is an output from server code. I did this with ClientLogin by just JSONPing their keyGen page and successfully consoleLogged the text even though it was b/w tags. I had some other errors on that but point is that I scraped that output.
Currently, I'm trying to do what you are so I'll post back if successful.
I don't think this is possible. JSONP requires that the response is rendered properly.
If you want another solution, what about loading the url in an iframe and trying to talk through the iframe. I'm not 100% positive it will work, but it's worth a shot.
First, call the AJAX URL manually and see of the resulting HTML makes sense.
Second, you need to close your DIV in your fiddle example.

Angular Routing with an encoded backslash

I am building in invite/registration form for my site. The idea is that one user invites another user, which sends a code with a url to register with. The problem is that the code can have an encoded backslash in it. When that encoded backslash is processed in Angular, it seems to get decoded and ends up busting the routing.
http://localhost:54464/ang/register/owi0%2fCQCrjzBcwqEORVVHhrICIANGKxtxMJ2Kh91y%2bNhhB%2br06appZzEVPhpkP2C
becomes:
http://localhost:54464/ang/register/owi0/CQCrjzBcwqEORVVHhrICIANGKxtxMJ2Kh91y+NhhB+r06appZzEVPhpkP2C
How can I stop this behavior?
Try using a route like:
/register/*code
The code will contain the string with the slashes
source
It is typically used for path-like url arguments...but I don't see why this wouldn't work for your case.

Nginx fallback for file not found to different directory with same path

Short Version: Is there any easy way to automatically redirect a path like /templates/my_child_theme/main/sidebar/user_nav.html to /templates/default/main/sidebar/user_nav.html whenever a 404 is encountered?
Question: Is there an easy way to use something like try_files within nginx to change a filepath when not found to a different folder with the same file path at the end? I'm currently using a client-side framework (AngularJS) and dealing with checking for the existence of files can get fairly expensive as I am literally performing an AJAX call for each file and looking for a 404 before performing the logic to swap out the path in Javascript. I've seen similar solutions for fallback images but haven't gotten a good solution yet. Here's the gist of what I'm looking to do:
Look for file at /templates/$1/$2.
On HTTP 404 instead return /templates/default/$2.
This only really needs to happen in the /templates/ location for now.
It's possible that these files could be nested several layers deep so I need something like /templates/my_child_theme/main/sidebar/user_nav.html to redirect to /templates/default/main/sidebar/user_nav.html
Backstory:
I've been building a site in AngularJS that has a fairly complex templating setup. I am utilizing the awesome ui-router module from Angular UI for deeply nested views and have written a few custom functions to implement child themes similar to Magento's fallback system. Here's what currently happens:
AngularJS requests a template path using a getTemplate() function I wrote which first looks for the file at /templates/child_theme_name_here/filepath by performing an XMLHttpRequest, checking for a status code of 404 (file not found), and then either returning that path or (in the case of a 404) returning /templates/default/filepath instead.
This way I can overload modify specific templates without needing to copy the entire theme each time, making development easier (we have 3 major corporate clients which will each have their own branded child theme) by not making me keep up with each change across multiple themes.
If there is a better way to do this within AngularJS I am open to that as well, it just seemed to me that Nginx would be the most logical place to perform such an action due to to it's low-level integration with the filesystem.
Solved.
Had to teach myself a bit on regular expressions, but finally got it working.
Here's what worked:
location ~* ^\/templates\/([^\/\\\]+)(.*)$ {
try_files /templates/$1$2 /templates/default$2 =404;
}
Regex Explanation
~* means case-insensitive matching (not really regex, just nginx syntax)
^ means start of a string
\/ means match a backslash
templates means literally match the word templates
\/ means match a backslash again
( means start capturing the following match as a group for later use
[^\\\/] means match anything that's not a backslash or forward slash means the previous set of characters can be matched multiple times (i.e. keep matching anything that isn't a slash.
) means stop capturing characters for this group. We have now defined the string that represents the first folder after /templates/
(.*) means match any other character as many times as needed (match everything that isn't a line feed in other words)
$ means match the end of the string
try_files then tries each URL in order
/templates/$1$2 means try /templates/(everything in capture group 1 above, which holds the folder we captured)(then add everything from capture group which holds the backslash and anything after it until the end of the url)
/templates/default$2 is very similar, except instead of using the text from capture group 1 ($1, the folder name we matched) we use the text "default" and then add everything from the second capture group to the end like before
=404 means that if neither of those worked return a 404 error
I'm seeing a significant speed improvement by moving this fallback mechanism into the server versus all of the extraneous calls I was forced to do before on the client.

AngularJS resource with explicit file type extension and POST

Angular $resource does a pretty good job figuring out how to handle POST and GET query with no resource ID; it intelligently removes the trailing slash:
resource('/users/:user',{user:'#id'},{})
Will give the correct:
GET /users/25 (for User.get())
POST /users (for new creation)
GET /users (for User.query())
Note that for creation and User.query() is correctly stripped the trailing slash when :user was blank.
However, if you add a file type extension, it stops stripping the trailing slash
resource('/users/:user.json',{user:'#id'},{})
Will give
GET /users/25.json (CORRECT)
POST /users/.json (BAD: should be /users.json)
GET /users/.json (BAD: should be /users.json)
Is there any way to get it to either:
intelligently strip the trailing slash even with a file type; OR
put on the '.json' extension afterwards
This is a pretty common pattern, supported as a basic format in Sinatra (RoR) and express (node), and is even part of the basic angular tutorial at http://docs.angularjs.org/tutorial/step_11
How do I get it to do the right thing?
I think it's a bug, which seems to be fixed in Version 1.1.5: https://github.com/angular/angular.js/commit/5306136

Resources