HttpServletRequest getting request parameters separated by # instead of? - spring-mvc

I am trying to get the Query String Parameters in the controller from the following URL using javax.servlet.http.HttpServletRequest object:
http://example.com:8080/OAuthClient/oauth-callback#access_token=something&expires_in=1209600&username=abcuser
It does not work because it is separated by # instead of ?
Hence it works if I change the request to http://example.com:8080/OAuthClient/oauth-callback?access_token=something&expires_in=1209600&username=abcuser
Is there a way to work around this problem? I have to make it work with # separated query parameters. which property will contain the data after oauth-callback?

Those aren't query parameters. They're the fragment of the URI - and that isn't sent to the server at all. It can only be used client-side.
From RFC 3986:
A fragment identifier component is indicated by the presence of a number sign ("#") character and terminated by the end of the URI.
... and (emphasis mine)
Fragment identifiers have a special role in information retrieval
systems as the primary form of client-side indirect referencing,
allowing an author to specifically identify aspects of an existing
resource that are only indirectly provided by the resource owner. As
such, the fragment identifier is not used in the scheme-specific
processing of a URI; instead, the fragment identifier is separated
from the rest of the URI prior to a dereference, and thus the
identifying information within the fragment itself is dereferenced
solely by the user agent, regardless of the URI scheme.

Related

the way to determine a request parameter is null

the way to determine a request parameter is null in spring
If you're talking about query or form parameters, then these cannot take value null. They are sent as strings; any conversion (e.g. to int) is done by the framework or your own application. So if a query parameter is sent in as ?var=null, then your applications gets 'null' - a string of length 4 containing the word null. So, if your application receives a null, then the query / form parameter was not sent.
It's a different story when you're talking about properties in JSON. If the type is simply String, Integer, etc., then you cannot see the difference between not-present and present as null. You can try using Optional<String> etc., but I haven't tried that myself. For Jackson you can find more information at https://www.baeldung.com/jackson-optional.
to make sure request parameter is not null and is always present you can use
#RequestParam(required = true)
This will make sure parameter is always passed

QMimeData encoding types

In my app I'm doing internal drag and drops with a QTreeView. Using the tutorial I can happily drag and drop a single leaf by encoding it into a string list using the mime type "application/vnd.text.list".
I then wanted to drag and drop a tree node that had some children and thought the best route to doing this would be to encode the pointer to the node and iterate through all the children in the dropMimeData method.
I declared a mime type in the mimeTypes() method:
QStringList toResultModel::mimeTypes() const {
QStringList types;
types << "text/plain";
types << "application/vnd.mypointerlist.list";
return types;
}
And tried to pass the same string list across, but the application crashes in the dropMimeData() method.
It seems the mime type "application/vnd.text.list" has some hidden meaning which I am unable to find.
I have found this source code: http://fossies.org/linux/tora/src/toresultmodel.cpp where the author sets up a custom coding type "application/vnd.tomodel.list" and also uses "application/vnd.int.list".
What are the rules in using encoding types?
Where are the built-in types strings defined?
Which type should I use for passing a pointer to a tree node?
Four years later...
From the information you give, if your method crashes, it's not related to Drag and Drop in particular, there is some error you need to find in the code. that said, let me clarify D&D in Qt, and answer your question about MIME types. While you have indeed solved the problem you had four years ago, this may be useful for other users today.
You may define your own type for the purpose of your application or reuse an existing one. How to choose?
Can you use an existing MIME type, like text/plain?
Think about your application being the target of a D&D operation initiated from another application. Can you accept an existing MIME type and retrieve your data from it?
Think about another application being the target of a D&D operation initiated from within your application. Could this application handle an existing MIME type?
If this answer is no to any of the questions, then you might have to use your own specific MIME type.
The format name itself is not important
The constraint is that it must be unique, so that you can't receive incorrectly formatted MIME data from another application, and other applications can identify the MIME type as one they cannot handle, and ignore it.
The exact MIME type name doesn't matter as you'll provide the encoder and the decoder into your data model (e.g. see this introduction to view/model for Qt), as well as other information about the MIME type(s) used.
In QAbstractItemModel::mimeTypes, list only the MIME types you are able to deal with. If you don't plan to accept or send MIME data from/to other applications, there is no need to allow more than your specific MIME type.
When your application is the source of a D&D operation, encode (serialize) the MIME data in QAbstractItemModel::mimeData(indexes). The result of the serialization must be a byte array, even when there are multiple indexes to be dragged. The internal format is yours. Include any information required to decode (de-serialize) MIME data. Note that you must provide encoded data in each of the MIME type you've listed in QAbstractItemModel::mimeTypes (see previous point).
When your D&D data are dragged over your application UI, QAbstractItemModel::canDropMimeData(self, mime_data, action, row, column, parent) is called to determine if this location is valid for a drop. You may determine here whether the drop should be allowed at this location. In particular, you may test the content of the MIME data provided, and use mime_data.hasFormat(mime_type) to check if the format you expect is found in the data about to be drooped. Returning false will prevent a drop at this location and a "not allowed here" indication will be provided to the user (this won't cancel the D&D operation itself, the user can continue to move the mouse elsewhere).
When the data is actually dropped, QAbstractItemModel::dropMimeData(mime_data, action, row, column, parent) is called. Get the MIME data format(s) used using QMimeData::hasFormat(mime_type). If you don't find the MIME type you expect, ignore the drop operation as you cannot decode the data provided (the D&D was initiated from another application). This shouldn't happen as prior to drop data, the application has called QAbstractItemModel::canDropMimeData as seen in the previous point. If everything is ok decode the MIME data, and update your model with the data received.
On the other hand, your tree leaf data may fit as path+name encoded in text/plain MIME data, so maybe you can just use this type too. However as other applications can generate text/plain data that don't contain a tree leaf description, you need, in this case, to have a mean to identify irrelevant data and ignore them. It's obvious such approach will need more code for verification of the validity of the drop action than when using a specific MIME type. However this allows to interact with other applications, and is indeed relevant to drag from well know applications like Excel (e.g. cell content) or Firefox (e.g. rich text or image), else we couldn't re-use information from these applications using D&D.
Do you need to use vnd prefix?
vnd in the MIME type means "vendor specific". This prefix is used to distinguish vendors created MIME types from those created by IANA authority. From RFC 6838:
Vendor-tree registrations will be distinguished by the leading facet
"vnd.". That may be followed, at the discretion of the registrant, by
either a media subtype name from a well-known producer (e.g.,
"vnd.mudpie") or by an IANA-approved designation of the producer's
name that is followed by a media type or product designation (e.g.,
vnd.bigcompany.funnypictures).
So in your Drag&Drop tutorial the application/vnd.text.list is a specific one supposedly created by some vendor for their own purpose. Same for application/vnd.mypointerlist.list
In contrast, text/plain is a standard MIME type defined by IANA in RFC 2046. This defines a human readable text:
Plain text does not provide for or allow formatting commands, font
attribute specifications, processing instructions, interpretation
directives, or content markup. Plain text is seen simply as a
linear sequence of characters, possibly interrupted by line breaks
or page breaks. Plain text may allow the stacking of several
characters in the same position in the text. Plain text in scripts
like Arabic and Hebrew may also include facilitites that allow the
arbitrary mixing of text segments with opposite writing directions.
For your type, you may want to use vnd followed by a subtype which is specific to your application, for consistency considerations. But as seen, the actual name is not important, as long as you know which one you use and you are not interacting with other applications in the D&D chain.

What's the RESTful way of attaching one resource to another?

this is one of the few moments I couldn't find the same question that I have at this place so I'm trying to describe my problem and hope to get some help an ideas!
Let's say...
I want to design a RESTful API for a domain model, that might have entities/resources like the following:
class Product
{
String id;
String name;
Price price;
Set<Tag> tags;
}
class Price
{
String id;
String currency;
float amount;
}
class Tag
{
String id;
String name;
}
The API might look like:
GET /products
GET /products/<product-id>
PUT /prices/<price-id>?currency=EUR&amount=12.34
PATCH /products/<product-id>?name=updateOnlyName
When it comes to updating references:
PATCH /products/<product-id>?price=<price-id>
PATCH /products/<product-id>?price=
may set the Products' Price-reference to another existing Price, or delete this reference.
But how can I add a new reference of an existing Tag to a Product?
If I wanted to store that reference in a relational database, I needed a relationship table 'products_tags' for that many-to-many-relationship, which brings us to a clear solution:
POST /product_tags [product: <product-id>, tag: <tag-id>]
But a document-based NoSQL database (like MongoDB) could store this as a one-to-many-relationship for each Product, so I don't need to model a 'new resource' that has to be created to save a relationship.
But
POST /products/<product-id>/tags/ [name: ...]
creates a new Tag (in a Product),
PUT /products/<product-id>/tags/<tag-id>?name=
creates a new Tag with <tag-id> or replaces an existing
Tag with the same id (in a Product),
PATCH /products/<product-id>?tags=<tag-id>
sets the Tag-list and doesn't add a new Tag, and
PATCH /products/<product-id>/tags/<tag-id>?name=...
sets a certain attribute of a Tag.
So I might want to say something link this:
ATTACH /products/<product-id>?tags=<tag-id>
ATTACH /products/<product-id>/tags?tag=<tag-id>
So the point is:
I don't want to create a new resource,
I don't want to set the attribute of a resource, but
I want to ADD a resource to another resources attribute, which is a set. ^^
Since everything is about resources, one could say:
I want to ATTACH a resource to another.
My question: Which Method is the right one and how should the URL look like?
Your REST is an application state driver, not aimed to be reflection of your entity relationships.
As such, there's no 'if this was the case in the db' in REST. That said, you have pretty good URIs.
You talk about IDs. What is a tag? Isn't a tag a simple string? Why does it have an id? Why isn't its id its namestring?
Why not have PUT /products/<product-id>/tags/tag_name=?
PUT is idempotent, so you are basically asserting the existance of a tag for the product referred to by product-id. If you send this request multiple times, you'd get 201 Created the first time and 200 OK the next time.
If you are building a simple system with a single concurrent user running on a single web server with no concurrency in requests, you may stop reading now
If someone in between goes and deletes that tag, your next put request would re-create the tag. Is this what you want?
With optimistic concurrency control, you would pass along the ETag a of the document everytime, and return 409 Conflict if you have a newer version b on the server and the diff, a..b cannot be reconciled. In the case of tags, you are just using PUT and DELETE verbs; so you wouldn't have to diff/look at reconciliation.
If you are building a moderately advanced concurrent system, with first-writer-wins semantics, running on a single sever, you can stop reading now
That said, I don't think you have considered your transactional boundaries. What are you modifying? A resource? No, you are modifying value objects of the product resource; its tags. So then, according to your model of resources, you should be using PATCH. Do you care about concurrency? Well, then you have much more to think about with regards to PATCH:
How do you represent the diff of a hierarchial JSON object?
How do you know what PATCH requests that conflict in a semantic way - i.e. we may not care about DELETEs on Tags, but two other properties might interact semantically.
The RFC for HTTP PATCH says this:
With PATCH, however, the enclosed entity contains a set of
instructions describing how a resource currently residing on the
origin server should be modified to produce a new version. The PATCH
method affects the resource identified by the Request-URI, and it also
MAY have side effects on other resources; i.e., new resources may be
created, or existing ones modified, by the application of a PATCH.
PATCH is neither safe nor idempotent as defined by [RFC2616], Section
9.1.
I'm probably going to stop putting strange ideas in your head now. Comment if you want me to continue down this path a bit longer ;). Suffice to say that there are many more considerations that can be done.

Optional Invalid Query String Variables

This is a somewhat philosophical issue. I have a .net (but could be any platform) based helper library that parses query string values. Take for example a variable that returns an Int32: my framework has an option that specifies whether this value is required or optional. If it is required but not provided, the framework throws an exception. If it is optional and not specified, it returns a null.
Now an edge case has come up based on users hacking (in a good way) our urls. If they specify a variable with either an invalidly formatted Int32 ("&ID=abc") or provide the variable but not specify a value ("&id="), should the framework throw an exception or should it return a null?
Part of me feels that invalid variables or formats should return a null. It might be valid to argue that even if the parameter is optional, an invalidly formatted query string or value should still throw an exception.
Thoughts?
Since this is philophical ...
On something like an ID, I would agree with Shawn that it is a 404, especially if you are thinking in terms of state. There is no object, so not found. But, ID may not tie directly to a resource in all cases.
If the item is truly optional, a null is okay. But optional should mean "if present it makes the call more specific" in this case and there should always be a fallback. I don't see this in ID, unless the ID is keyed to an optional part of the page.
In the long run, I think you should look at the business reason for the page and what each variable means.
I believe that if a variable is optionaly, providing the variable but not specifying the value is equivalent to ommitting the variable itself. In this case, returning null seems OK.
However, providing an invalidly formatted value ought to cause an Exception, since the intent was to provide a value. In this case the user ought to be notified through some sort of validation mechanism.
A HttpException of 404 (Not Found). Your web application framework should know how to catch these errors and redirect to the proper page.
This is actually a not found error because the resources that the ID is pointing to does not exist.
I suspect there's no "right" answer to your question. If I were a developer using your library, I would expect/hope that the public API would include in its code comments, a description of how the function behaves when the URL param includes bad (wrong type) data.
You might also be able to craft your public API to get the best of both worlds: .NET seems to have adopted the "Parse" / "TryParse" approach in many places. If I'm the caller and I want the function to throw if given invalid data, I call Parse(). If I don't want it to throw, I call TryParse(). In my opinion, that is a nice pattern to follow with your API as well.

What options to I have to pass a value between two asp.net pages

I want to know what the best practice is for passing values (sometimes multiple values) between two asp.net pages
In the past I have used query strings to pass a value in asp like this:
href='<%# Eval("TestID","../Net/TestPage.aspx?TestID={0}") %>'><%#Eval("Title")%> </a>
I assume you can do this in the code behind but I do not know the best way.
I also assume it is possible to pass more than one value.
Could someone provide me with a VB snippet which would give me an idea of how to go about this?
You have many options for passing data and all of them can pass multiple values between pages.
You can use the Request.Form collection to capture values that have been submitted from an HTML form with the POST verb (i.e. " method="POST">).
The code looks something like:
Dim formvalue As String
formValue = Request.Form("FormField1")
You can also use parameters in a URL query string (much like you example):
Dim queryStringValue As String
queryStringValue = Request.QueryString("QueryStringValue1")
You can set a cookie (it's lifetime will depend on the Expiry property value that you set):
Setting a cookie (note: you use the HttpResponse object here. The user's browser stores the cookie when it receives the Set-Cookie HTTP header value from the response to a request)
Response.Cookies("CookieValue") = "My Cookie Data"
Response.Cookies("CookieValue").Expires = DateTime.Now.AddDays(1) ' optional, expires tomorrow
Retrieving a cookie value (we use the HttpRequest object here):
Dim cookieValue As String
cookieValue = Request.Cookies("CookieValue")
You can use the HttpSessionState object (accessible via the Session property of a page). To set a session variable:
Session["SessionValue"] = "My Session Value"
To retrieve a session value:
Dim sessionValue As String
sessionValue = Session["SessionValue"]
There's another way to pass page state between pages using Page.Transfer (see How to: Pass Values Between ASP.NET Web Pages), but I'd try and get comfortable with the above before looking into that.
As far as best practices go it really depends on what data you're passing.
Don't pass sensitive data via URLs (query strings), forms or cookies. These can intercepted in various ways
Pass sensitive data using a server-side store (like session state or a database) but consider how to keep the session ID safe.
Never trust data from outside your application (data that users have entered via a form, information read from a database, etc.). Always encode this information before displaying it again in your pages. This prevents against Cross-Site Scripting (a.k.a XSS) attacks.
Don't use sequential IDs in query strings where you're passing user-specific identifiers between pages. Say you create an Orders.aspx page that lists all orders for a customer. You pass in a CustID parameter via a query string: Orders.aspx?CustID=123. It's easy for someone to change the URL to Orders.aspx?CustID=124 and view information they shouldn't. You can get around this by doing a check that the current user is allowed to see the information, you can use an identfier that can't be easily guessed (commonly a GUID) or pass the information on the server-side.
It would help you to check out the following links:
a. Cross page postbacks
b. How to pass values between ASP.NET pages (MSDN)
c. Another article by Steve C. Orr on Passing values.
You can use a session, cookies, the query string, hidden form fields in a post request.

Resources