I am new to REST API's.
I am developing a REST API.
In the following API the parameters I take is cloud-id.
This is the API Call:
#GET
#Path("{cloud-id}")
#Produces("application/json")
public Object Getall(#PathParam("cloud-id") String cloudID) {
if(cloudID!=null){
//return some details
}else{
//return something else
}
}
Happy Path:
http://example.com/sampleCloudID
This also works fine
http://example.com/(sampleCloudID)
It gives a 404 as expected
But when I give the URI as
http://example.com/{sampleCloudID}
ERROR:
You specified too few path parameters in the request.
In case the input I receive is {samplecloudID} I expect the service to return a 404, but I am unable to reach my resource if the path variable is in {}.
Why are curly braces giving me a error but normal parenthesis give 404 as expected ?
If you need to send special characters as part of the URL you need to encode them.
try using http://example.com/%7BsampleCloudID%7D
This should let your controller get the {}
This wikipedia article should give you details.
RFC 1738 states that certain characters are unsafe in URLs:
Unsafe:
Characters can be unsafe for a number of reasons. [...] Other
characters are unsafe because gateways and other transport agents are
known to sometimes modify such characters. These characters are "{",
"}", "|", "", "^", "~", "[", "]", and "`".
All unsafe characters must always be encoded within a URL. For
example, the character "#" must be encoded within URLs even in systems
that do not normally deal with fragment or anchor identifiers, so that
if the URL is copied into another system that does use them, it will
not be necessary to change the URL encoding.
source: https://meta.stackexchange.com/questions/79057/curly-brackets-in-urls?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa
You could write code this way in which you did't get any error on changing type of your path variable
#GetMapping(value = { "/your-path/{cloud-id}", produces = "application/json")
public Object Getall(#PathVariable(value = "cloud-id", required = false) String cloudID) {
//do your stuff
}
Related
I sent one request as URL with data to servlet, But by default servlet is modifying the data and sending as request. Can you please suggest how to maintain the request URL with data which i passed to servlet should remain same ?
Example:- when i am passing the data to servlet
http://localhost/helloservlet/servlet/ppd.abcd.build.coupons.CouponValueFormatterServlet?dsn=frd_abc_abcde&lang=ENG&val=PRCTXT|12345 &ABCDEFG
when it using the above url in servelt as request , like string abc = request.getParameter("val"), the val attribute is trimmed automatically and assigned as " val=PRCTXT|12345" but it supposed to be like " val = PRCTXT|12345 &ABCDEFG ". Please help me on this.
The servlet interprets each & in the URL as the start of a new parameter. So when it sees &ABCDEFG, it thinks you are sending a new parameter called ABCDEFG with no value (though this is technically a "keyless value" according to the specifications).
Two things to fix this, first is when you want to actually send an &, use %26 instead. This will be skipped by the code that divides up the parameters, but converted to a real & in the parameter's value.
Second is to replace spaces with +. Spaces in URLs work sometimes but can be problematic.
So your actual request URL should look like this:
http://localhost/helloservlet/servlet/ppd.abcd.build.coupons.CouponValueFormatterServlet?dsn=frd_abc_abcde&lang=ENG&val=PRCTXT|12345+%26ABCDEFG
If you're building these parameters in javascript, you can use encodeURIComponent() to fix all problem characters for you. So you could do something like this:
var userInput = *get some input here*
var addr = 'http://www.example.com?param1=' + encodeURIComponent(userInput);
I am working on a project in that java script as front-end and java as back-end are used, my problem is that I want to pass some string using restangular calls to my back-end resources. If passing parameter have space between the string then I got 500 (Server Error) before reaching to back-end resource side.
Lets take example :
At Java Script : RESTangular call
var myRestCall= Restangular.all('myRoot/myMethod/'+myLocalPath+'/'+folderName);
restPSTFolders.getList().then(function(listPSTFolders){
//my stuff
});
At Java Resource :
#ApiOperation(value = "My Method",
notes = "Returns My Method list",
responseContainer = "List",
response = List.class)
#Path("/myMethod/{myLocalPath}/{folderName}")
#GET
#Transactional
#Timed
public List myMethod(#PathParam("myLocalPath") String myLocalPath, #PathParam("folderName") String sFolderName) {
//my stuff
}
In my example myLocalPath parameter can have spaces and special characters in the string as it can be any :
C:\MY DRIVE\My Path One\My Path
D:\My favorite
To pass this to back-end class from RESTangular call, I need to replace all spaces with some character, it work for me, but I am not thinking its a good way to encode the special character and space with any character because the replacing character can also be a part of existing path then at back-end on again replacing the character, might change the path.
EDIT : If I passed the parameter as json object:
var parameterJsonPath = {};
parameterJsonPath={"myLocalPath": pathValue};
var myRestCall= Restangular.all('myRoot/myMethod/'+parameterJsonPath+'/'+folderName);
Does not make any sense as I got : ../myRoot/myMethod/%5Bobject%20Object%5D Failed to load resource: the server responded with a status of 500 (Server Error)
And making the parameterJsonPath to JSON.stringify(parameterJsonPath); will pass this as string that of no use for me.
Thus in all, is there any good way to encode the special character of string in js, so at back-end side I could decode that string using same key that were used while encoding?
(Camel 2.9.2)
Very simple use case, but I can't seem to find the answer. My code boils down to this:
String user = "user";
String password = "foo&bar";
String uri = "smtp://hostname:25?username=" + user +
"&password=" + password +
"&to=somthing#something.com"; // etc. You get the idea
from("seda:queue:myqueue").to(uri);
Camel throws a ResolveEndpointFailedException with "Unknown parameters=[{bar=null}]."
If I try "foo%26bar," I get the same result.
If I try "foo&bar" camel responds with "Unknown parameters=[{amp;bar=null}]."
I tried using URISupport to create the URI. It escapes the & to %26, and then I get "Unknown parameters=[{bar=null}]" again.
Any ideas?
As from Camel 2.11 you could use raw syntax
For instance:
.to("ftp:joe#myftpserver.com?password=RAW(se+re?t&23)&binary=true"
In the above example, we have declare the password value as raw, and
the actual password would be as typed, eg se+re?t&23
https://cwiki.apache.org/confluence/display/CAMEL/How+do+I+configure+endpoints
You can specify the password as part of the authority of the uri, eg in the front.
Also the & should be escaped to %26, but there was a bug in Camel that didnt parse the escaped value to well. Try 2.10 when its out.
The RAW() syntax works, yet it is Camel-proprietary syntax. In our usecase it burdened following processing of URI.
We used alternative solution: component configured as using raw URIs (Component.useRawUri() == true). Component parameters are then simply once encoded (foo%26bar) and pass through Camel without change. I consider this solution better as percent-sign encoding is standard way of expressing sensitive characters.
I have my application url which I am sending the the end user on their emails.
Now that url contains the 'username' field, which can contains '#' character.
For e.g. link which sent to the end user :
http://localhost:8080/my-app/someaction/activateuser/abc#def.com/somedata/
Now whenever user clicks on above link, its throwing following exception :
java.lang.IllegalArgumentException
Input string 'abc#def.com' is not valid; the character '#' at position 4 is not valid.
at org.apache.tapestry5.internal.services.URLEncoderImpl.decode(URLEncoderImpl.java:144)
at $URLEncoder_137022607d9.decode($URLEncoder_137022607d9.java)
at org.apache.tapestry5.internal.services.ContextPathEncoderImpl.decodePath(ContextPathEncoderImpl.java:92)
at $ContextPathEncoder_137022607cd.decodePath($ContextPathEncoder_137022607cd.java)
at org.apache.tapestry5.internal.services.ComponentEventLinkEncoderImpl.checkIfPage(ComponentEventLinkEncoderImpl.java:328)
at org.apache.tapestry5.internal.services.ComponentEventLinkEncoderImpl.decodePageRenderRequest(ComponentEventLinkEncoderImpl.java:307)
at org.apache.tapestry5.internal.services.linktransform.LinkTransformerInterceptor.decodePageRenderRequest(LinkTransformerInterceptor.java:68)
at $ComponentEventLinkEncoder_137022607c1.decodePageRenderRequest($ComponentEventLinkEncoder_137022607c1.java)
at org.apache.tapestry5.internal.services.PageRenderDispatcher.dispatch(PageRenderDispatcher.java:41)
at $Dispatcher_137022607c2.dispatch($Dispatcher_137022607c2.java)
at $Dispatcher_137022607bd.dispatch($Dispatcher_137022607bd.java)
at org.apache.tapestry5.services.TapestryModule$RequestHandlerTerminator.service(TapestryModule.java:321)
at org.apache.tapestry5.internal.services.RequestErrorFilter.service(RequestErrorFilter.java:26)
Is there any way to handle such scenario, like encoding/decoding the urls ?
You cannot have an # in the url, because it's a reserved character (the specific RFC is RFC 3986).
You can use the URLEncoder class to encode the url to an acceptable value
As MiniBill has already answered, that can't work, and as Howard has added, Tapestry has its own encoder for URLs. This means that the easiest way for you to get a URL in the format that Tapestry can read is to have Tapestry create it, and then pass it to the component that sends your emails:
#Inject
private LinkSource linkSource;
#OnEvent(...)
void sendActivationEmail() {
final Link activationLink = this.createUserActivationLink(email, otherStuff);
this.activationEmailSender.sendWithActivationLink(email, activationLink);
}
private Link createUserActivationLink(String email, String otherStuff) {
return linkSource.createPageRenderLink(
"someaction/activateuser", false, email, otherStuff);
}
I was able to solve the problem by encoding my string to Base64, and unpacking on Tapestry Java side. My strings were of UTF-8 encoded characters.
I modified the Base64 encoder from this answer: https://stackoverflow.com/a/40392850/5339857
function b64EncodeUnicode(str) {
return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function(match, p1) {
return String.fromCharCode('0x' + p1);
})).replace(/\=+$/, '');
}
(just added the .replace in the end, to remove padding =s that Tapestry doesn't like)
And in the Java side the decoding was a breeze: (this example is of an ajax click from javascript - where the Base64 encoding happens)
#OnEvent(value = "clickAjax")
Object clickAjax(String parameter) {
somePagePropetry = new String(java.util.Base64.getDecoder().decode(parameter));
return this;
}
I am trying to use Twitter OAuth and my POST requests are failing with a 401 (Invalid OAuth Request) error.
For example, if I want to post a new status update, I am sending a HTTP POST request to https://twitter.com/statuses/update.json with the following parameters -
status=Testing&oauth_version=1.0&oauth_token=xxx&
oauth_nonce=xxx&oauth_timestamp=xxx&oauth_signature=xxx&
oauth_consumer_key=xxx&in_reply_to=xxx&oauth_signature_method=HMAC-SHA1`
My GET requests are all working fine. I can see on the mailing lists that a lot of people have had identical problems but I could not find a solution anywhere.
I am using the oauth.py Python library.
I just finished implementing twitter OAuth API from scratch using Java. Get and post requests work OK. You can use this page http://www.hueniverse.com/hueniverse/2008/10/beginners-gui-1.html to check signature and HTTP headers. Just enter your keys and tokens and check output. It seems twitter works exactly as described on this post. Be careful with spaces and UTF-8 symbols, for example Java encodes space as "+" but OAuth requires %20
Make sure your app access type is read & write.
On your app settings page (ex. http://twitter.com/apps/edit/12345) there's a radio button field like this:
Default Access type: Read & Write / Read-only
If you check 'Read-only' then status update API will return 401.
I second the answer by Jrgns. I has exactly the same issue. When reading the example Twitter provides, it's actually clear. However their pseudo code is misleading. In Python this worked for me :
def encodekeyval(key, val):
key = urllib.quote(key, '')
val = urllib.quote(val, '')
return urllib.quote(key + '=' + val, '')
def signature_base_string(urlstr, oauthdata):
sigstr = 'POST&' + urllib.quote(urlstr,'') + '&'
# retrieve "post" data as dictionary of name value pairs
pdata = oauthdata.getpdata()
# need to sort parameters
pstr = '%26'.join([encodekeyval(key, pdata[key]) for key in sorted(pdata.keys())])
return sigstr + pstr
I had the same issues, until I realised that the parameters need to be encoded twice for the base string. My GET requests all worked fine, but my POSTs, particularly status updates, failed. On a hunch I tried a POST without spaces in the status parameter, and it worked.
In PHP:
function encode($input) {
return str_replace('+', ' ', str_replace('%7E', '~', rawurlencode($input)));
}
$query = array();
foreach($parameters as $name => $value) {
$query[] = encode($name) . '=' .encode($value);
}
$base = encode(strtoupper($method)) . '&' .encode($norm_url) . '&' .
encode(implode('&', $query));
Notice the encode function around the names and values of the parameters, and then around the whole query string. A Space should end up as %2520, not just %20.
I found the solution and it works for me, You must add the following paramters in the request header and it should look like following (c# code), donot use & sign, instead separate parameters by comma(,) sign. and you must add the word "OAuth" in the beginging.
httpWebRequest.Headers[System.Net.HttpRequestHeader.Authorization] = "OAuth oauth_consumer_key=\"hAnZFaPKxXnJqdfLhDikdw\", oauth_nonce=\"4729687\", oauth_signature_method=\"HMAC-SHA1\", oauth_timestamp=\"1284821989\", oauth_token=\"17596307-KH9iUzqTxaoa5576VjILkERgUxcqExRyXkfb8AsXy\", oauth_version=\"1.0\", oauth_signature=\"p8f5WTObefG1N9%2b8AlBji1pg18A%3d\"";
and other parameters like 'status' should be written in the body of the request.
Most likely, the signature is invalid. You must follow the OAuth spec on how to generate the signature( normalized parameters, URLencoding, and cosumerSecret&oauthScret. More on this later ......