Http resource request method and Grails server - grails

I'm building a controller which delivers image from Linux file system. And I need to force request http method.
on gsp side I have something like :
<div style="background-image: url('${createLink(controller: 'customServing', action:'imageserv', params: [param1: 'foo'])}');"></div>
controller side is :
static allowedMethods = [index: 'GET',
imageserv: ['POST']]
the action look like:
def imageserv = {
ByteArrayOutputStream baos=new ByteArrayOutputStream()
ImageIO.write(originalImage, "png", baos )
ImageIO.write(ImageIO.read(new File(whateverPic)),'png',baos)
byte[] imageAsByte = baos.toByteArray()
response.setHeader('Content-length', imageAsByte.length.toString())
response.contentType = 'image/png'
response.outputStream << imageAsByte
response.outputStream.flush()
}
The web browser will automatically issue a request to get the background
image: Remote Address:[::1]:8080
Request URL:http://localhost:8080/customServing/imageserv?param1=foo
Request Method:GET
I would have used Ajax or classic javascript to format my request, but I can't because of conception needs. (so it also implies grails remote link, or html form manually fired submit event are not valid option)
Is there any way to indicate (client side or server side) browser to issue only POST request for page resource rendering?
edit: I do have total control over context environment (Cent OS 7, Tomcat 8)

Related

Error in Access-Control-Allow-Origin when Angular request to Rails

I'm using Angular 2 to make an API(rails) request. When I make the http request through angular, I get the following error:
XMLHttpRequest cannot load https://api-url. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:4200' is therefore not allowed access. The response had HTTP status code 404.
However, if I try to make a request through Postman or the browser itself, I don't get any error. The data is displayed normally
angular code:
makeRequest() {
let user = {"user": "user", "password": "password"};
let headers: Headers = new Headers();
headers.append('Authorization', 'Basic ' + btoa(user.user + ':'+user.password));
headers.append('Content-Type', 'application/vn.api+json')
let this.http.get(api-url, {headers: headers}).map(res => res.json()).subscribe(data => {
this.data = data;
})
}
In my rails server i using the gem 'jsonapi-resources'to open AP. In my api controller, i have this code to authenticate and set headers to requests:
module Api
class ApiController < JSONAPI::ResourceController
prepend_before_action :set_headers, :authenticate
def context
{ current_station: #user }
end
private
def authenticate
authenticate_or_request_with_http_basic do |token, _|
#user = User.where(api_key: token).first
end
end
def set_headers
response.headers["Access-Control-Allow-Origin"] = "*"
end
end
end
When i make request in browser or using postaman, the header appears normally, but in Angular i have the error.
This is because of CORS. Long story short, browsers forbid by default one domain (http://localhost:4200) to make AJAX requests to another one (http://api-url). It works in "postman" because this is an extension and then, the CORS does not apply. If you want to fix this issue, you have to configure your server to returns certain header saying to the client that it allows the CORS connection.
In fact, when a website is trying to make an AJAX request to another domain, it first send an OPTION request to ask what are the domain allowed. This list is returned by the server via the header Access-Control-Allow-Origin. For example, it could contain a star ("*") to indicate that anyone could make AJAX call to this server. If this header allows your client to make AJAX call, your actual request will be executed, otherwise, you'll get an error (probably the one you currently get)

Browser caching of images served by Grails

I have a controller action which reads an image from the database and serves it to the client:
def profilePicture() {
def profilePicture = ProfilePicture.get(1)
response.setHeader("Content-disposition", "attachment; filename=1.png")
response.contentType = "PNG"
response.outputStream << profilePicture.profilePicture
response.outputStream.flush()
}
Every time the client requests the image, the server serves the whole image with status 200. What can I do to instruct the client that this content can be cached?
I have already tried response.setHeader("Expires", "...") with a date in the future but this didn't help (I'm guessing this is only part of the story as the server is not returning 304).
Actually, there is a plugin called Caching Headers for Grails which will handle all the needed caching and etag generation so that browsers won't request the download of the file when it's not modified and within your configured caching period.
It's pretty simple to use if you read through the documentation and take your time to test your configuration.

grails controller handling ajax file upload

I am implementing a file uplaod via jquery ajax but I fail to do something with the data on the controller side. I get the params but not the File which is in this example a jpeg. The data is in the Request Payload.
My problem is on server side. How do I get a File on server side?
#Secured(['ROLE_USER', 'ROLE_ADMIN', 'ROLE_PARTNER', 'ROLE_READ_ONLY', 'ROLE_USER_PAYING'])
def fileupload () {
println "---------------------------------------------------"
params.each{
println it.key +"="+ it.value
}
request.getHeaderNames().each{
println (it)
}
render("OK")
}
This is the output i receive:
---------------------------------------------------
filename=1506368_10152113826431683_327028558_o.jpg
apiKey=c7937acaf6d5411d8920d194dc48c041
action=fileupload
controller=post
host
connection
content-length
...
How do I get the file in my controller?
I'm doing the same, and using request.getInputStream() in the controller for getting the binary data. This actually comes from the ServletRequest interface - see http://docs.oracle.com/javaee/7/api/javax/servlet/ServletRequest.html#getInputStream--

XMLHttpRequest Post Method - Headers are stopping function

I'm trying to send an XMLHttpRequest object to my Rails server but the headers are causing my function to stop. Here are my observations:
When I comment out the 3 lines of code that set the headers, then xhr.readyState will eventually equal 4 (alert boxes within the anonymous function fire off).
If any one of the 3 header lines are uncommented, then the xhr object never changes state (none of the alert boxes ever fire off).
function saveUserProfile(){
var user_email = $('#userEmail_box').val();
var xhr = new XMLHttpRequest();
xhr.onreadystatechange=function(){
if (xhr.readyState==4 && xhr.status==200)
{
alert("Yes: " + xhr.readyState);
}
alert("No: " + xhr.readyState);
}
var method = 'POST';
var params = 'userEmail=user_email';
var url = 'http://localhost:3000/xhr_requests.json';
var async = true;
//Need to send proper header information with POST request
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.setRequestHeader('Content-length', params.length);
xhr.setRequestHeader('Connection', 'close');
xhr.open(method, url, async);
xhr.send(params);
}
My three questions are:
What do I need to change in the code above in order to send data through the POST method?
I'm under the impression that the POST method requires some headers to be sent but am not clear about which ones though "xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');" seems to be one that is often mentioned in references. Can somebody help me understand a) why headers need to be sent and b) which ones need to be sent?
I'm using a rails server and am developing locally. Ultimately, this code will be executed on the client side of a mobile device which will go to a hosted rails server for passing and receiving data. Are there limitations with using the POST method with a rails server? Keep in mind that I plan to use JSON when sending information to the client from the server.
Thanks!
UPDATE: The headers should come AFTER the opening the xhr request but BEFORE sending it:
xhr.open(method, url, async);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.setRequestHeader('Content-length', params.length);
xhr.setRequestHeader('Connection', 'close');
xhr.send(params);
Hope this post saves somebody else 4 hours.
Does your web page with the JavaScript code also live on localhost:3000? If not, this is considered a cross-domain request, and your server will need to return special headers. So you have two options:
1) Host the web page on the same domain as the server, which will make this a same-domain request.
2) Have your server return the appropriate CORS headers. You can learn more about CORS here: http://www.html5rocks.com/en/tutorials/cors/

POST request and Node.js without Nerve

Is there any way to accept POST type requests without using Nerve lib in Node.js?
By default the http.Server class of Node.js accepts any http method.
You can get the method using request.method (api link).
Example:
var sys = require('sys'),
http = require('http');
http.createServer(function (request, response) {
response.writeHead(200, {'Content-Type': 'text/plain'});
response.write(request.method);
response.end();
}).listen(8000);
sys.puts('Server running at http://127.0.0.1:8000/');
This will create a simple http server on the port 8000 that will echo the method used in the request.
If you want to get a POST you should just check the request.method for the string "POST".
Update regarding response.end:
Since version 0.1.90, the function to close the response is response.end instead of response.close. Besides the name change, end can also send data and close the response after this data is sent unlike close. (api example)

Resources