Play framework 2.1 HTTP HEAD method response - scala

How can I return a only response header(HTTP HEAD method) on scala play framework 2.1?

Unfortunatelly there is Java solution but maybe you will 'convert' it to Scala, general concept is:
Catch HEAD request send it to dedicated method
The method autoHead(String originalPath) sends a GET request using WebServices forwarding params and returning only status of the response.
It adds additional header X_FORWARD_FROM_HEAD so if ie your action is logging something to the DB after each hit you can avoid that for HEAD requests.
code:
/**
* Tries to get headers of resource with WebServices and return headers only.
*
* #param originalPath Path of the resource
* #return Headers for HEAD request
* #throws IllegalAccessException
*/
public static Result autoHead(String originalPath) throws IllegalAccessException {
WS.WSRequestHolder forwardedRequest = WS.url("http://" + request().host() + request().path());
// this header will allow you to make additional choice i.e. avoid tracking the request or something else
// see condition in index() action
forwardedRequest.setHeader("X_FORWARD_FROM_HEAD", "true");
// Forward original headers
for (String header : request().headers().keySet()) {
forwardedRequest.setHeader(header, request().getHeader(header));
}
// Forward original queryString
for (String key : request().queryString().keySet()) {
for (String val : request().queryString().get(key)) {
forwardedRequest.setQueryParameter(key, val);
}
}
// Call the same path but with GET
WS.Response wsResponse = forwardedRequest.get().get();
// Set returned headers to the response
for (Field f : Http.HeaderNames.class.getFields()) {
String headerName = f.get(null).toString();
if (wsResponse.getHeader(headerName) != null) {
response().setHeader(headerName, wsResponse.getHeader(headerName));
}
}
return status(wsResponse.getStatus());
}
/**
* Checks if request if forwarded from HEAD request
*
* #return true if 'X_FORWARD_FROM_HEAD' header exists and is set to true
*/
public static boolean forwardedFromHead() {
return (request().getHeader("X_FORWARD_FROM_HEAD") != null && "true".equals(request().getHeader("X_FORWARD_FROM_HEAD")));
}
routes:
HEAD / controllers.Application.autoHead(originalPath:String ?= "/")
HEAD /*originalPath controllers.Application.autoHead(originalPath:String)

You can add a HEAD route, next to the GET route, like this:
GET /assertion controllers.Assertion.get
HEAD /assertion controllers.Assertion.head
In the implementing method, you can call the GET method and pass a flag to suppress the body, I guess.

What about returning EmptyContent as a content
Action {
....
Ok(EmptyContent())
}

Related

check if api endpoint exits before send request - axios

I have axios request in my vue application:
async get_banner(id:number) : Promise<any> {
return global.axios.get(`${process.env.VUE_APP_DOMAIN}/banners/${id}`)
}
it works while banner/${id} response exits, but I have situation when I should disable banner in my admin panel so api endpoint becomes empty. (not exits) so I am getting Request failed with status code 404 in my vue app console.
question is how to prevent error and know if url exits or not? what is best practice to do this?
You can't tell whether an API exists or not without trying it (or relying on another API to get status of the former API)
It's usually just a manner of handling the response properly. Usually this would look something like this...
getTheBanner(id){
this.errorMessage = null; // reset message on request init
get_banner(id)
.then(r => {
// handle success
this.results = r;
})
.catch(e => {
// handle error
if (e.status === 404){
// set error message
this.errorMessage = "Invalid banner Id";
}
})
}
then in your template you could have something like this
<div v-if="errorMessage" class="alert danger">{errorMessage}</div>
Explaination:
Yes, you're absolutely right. This is the default behavior of strapi. Whenever the response is empty it throws a 404 error. This is basically because the findOne method in service returns null to the controller and when the controller sends this to the boom module it returns a 404 Not Found error to the front end.
Solution:
Just override the find one method in the controller to return an empty object {} when the response is null.
Implementation
// Path - yourproject/api/banner/controllers/banner.js
const { sanitizeEntity } = require('strapi-utils');
module.exports = {
/**
* Retrieve a record.
*
* #return {Object}
*/
async findOne(ctx) {
const { id } = ctx.params;
const entity = await strapi.services.restaurant.findOne({ id });
// in case no entity is found, just return emtpy object here.
if(!entity) return {};
return sanitizeEntity(entity, { model: strapi.models.restaurant });
},
};
Side Note:
There's no need to make any changes to the browser side axios implementation. You should always handle such cases in controller rather the client side.
Reference:
Backend Customizations

Headers in POST in Grails 3 app are not being sent with rest of service

Using Grails 3.0.9, and grabbing the freshest REST API with this snippet in gradle.build:
compile 'org.grails:grails-datastore-rest-client:4.0.7.RELEASE', {
['commons-codec', 'grails-async', 'grails-core',
'grails-plugin-converters', 'grails-web', 'groovy'].each {
exclude module: it
}
}
I am trying to make the following POST request:
def rest = new RestBuilder(headers:["X-LSS-Env":"devmo"], connectTimeout:10000, readTimeout:20000)
response = rest.post("http://..../..") {
accept "application/json"
contentType "application/json"
json jsonBuilder
}
Now, the POST receiver gets the json okay, give back a response okay, but this is the problem: it receives the headers as an empty map or as null!
So, what is the correct way of passing header data to the POST receiver? This is needed because the environment key X-LSS-Env could have different values, which instructs the receiver to do further routing based on it. Same with the GET request of course.
* UPDATE *
The consumer of my POST requests is actually a Java application, running on Apache Tomcat/8.0.26. The is how the service looks on the other side:
private javax.servlet.http.HttpServletRequest hsr;
#POST
#Path("/na")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public Response postSomething(Ggfp ggfp ){
try {
Enumeration<String> hnames = hsr.getHeaderNames();
int i = 0;
while (hnames.hasMoreElements()) {
String headerName = hnames.nextElement();
System.out.println(++i+ " headerName: " + headerName);
String val = hsr.getHeader(headerName);
System.out.println(" val: " + val);
}
String hval = hsr.getHeader("X-LSS-Env");
return Response.status(Status.OK).entity("X-LSS-Env is " + hval).build();
} catch (Exception e) {
}
}
Calling this service from Postman works, headers are identified. Calling it from the Grails app results into an empty map - like I am sending no headers!
The RestBuilder constructor never liked the way I used (or abused) it. Here is a clean way of achieving what I set out to do, with tryCatch logic if a timeout transpires.
def makePostWsr(serviceUrl, jsonBuilder) {
try {
def rest = new RestBuilder(connectTimeout:connectTimeout, readTimeout:readTimeout)
def response = rest.post("$wsUrl/$serviceUrl") {
header 'X-LSS-Env', 'devmo'
accept "application/json"
contentType "application/json"
json jsonBuilder
}
response
} catch (Exception e) {
println "== problem makePostWsr on $serviceUrl"
null
}
}

Wicket 6.x https with other host

I have a webpage with a area where users can login. This area
www.host.com/mypage/myarea
should be under https.
The problem is that my https is running on a another host:
www.something-foo.host.com/mypage/myarea
. (loadbalancer stuff...??? I dont know why)
My try is to annotate the Pages with #RequireHttps, an than rewrite the urls of the Pages.
But how and where? Has someone please an example?
Thanks for your help.
Well if you really want to this with Wicket your best option would be to write an implementation of IRequestMapperDelegate and set them during the onInit() process of your WicketApplication.
To give you an idea how to do this I've written an example of raping the HttpsMapper of Wicket:
setRootRequestMapper(new HttpsMapper(getRootRequestMapper(), new HttpsConfig(8080, 8443)) {
private final static String SUBDOMAIN = "www.something-foo.";
#Override
protected Scheme getSchemeOf(Request request) {
HttpServletRequest req = (HttpServletRequest) ((WebRequest) request).getContainerRequest();
// well that's basically cheating and not so nice... but we're not allowed to overwrite mapRequest()
// but that means that every request that doesn't start with the subdomain will be treated as HTTP aka
// insecure.
if (req.getServerName().startsWith(SUBDOMAIN) == false) {
return Scheme.HTTP;
}
return super.getSchemeOf(request);
}
#Override
protected String createRedirectUrl(IRequestHandler handler, Request request, Scheme scheme) {
// stolen from super implementation
HttpServletRequest req = (HttpServletRequest) ((WebRequest) request).getContainerRequest();
String url = scheme.urlName() + "://";
// except the part where we insert the subdomain
url += SUBDOMAIN;
url += req.getServerName();
if (!scheme.usesStandardPort(getConfig())) {
url += ":" + scheme.getPort(getConfig());
}
url += req.getRequestURI();
if (req.getQueryString() != null) {
url += "?" + req.getQueryString();
}
return url;
}
});
Depending on your question I can't really determine if this is a good solution ... it really depends on how many frameworks are working on top of Wicket. Since you didn't mention anything else I'm assuming none.

Is there a quick built in way to forward a request in the scala Play framework

I'm looking for something like
def proxy = Action.async { implicit req =>
//do something with req
val newRequest = req.map( r = r.path = "http://newurl");
forward(newRequest)
}
I saw that there is a redirect method but that only allows me to pass the request parameters and not everything else, headers, etc.
I am hoping there is something built in so I don't have to build it myself.
I'm not sure if this meets your requirements, but have you had a look into Play's WS.
The action forwardTo gets an url, fetches the according page and returns it as this request's response. It's not exactly like an forward in the Spring framework but it does the job for me.
/**
* Like an internal redirect or an proxy. The URL in the browser doesn't
* change.
*/
public Promise<Result> forwardTo(String url) {
Promise<WS.Response> response = WS.url(url).get();
return response.map(new Function<WS.Response, Result>() {
public Result apply(WS.Response response) {
// Prevent browser from caching pages - this would be an
// security issue
response().setHeader("Cache-control", "no-cache, no-store");
return ok(response.getBody()).as("text/html");
}
});
}
(I'm using Play 2.2.3)

How to get currentPagePath in Slingservlet?

From some javascript I call the following Slingservlet with ("/bin/fooServlet?"+params);
#SlingServlet(paths = "/bin/fooServlet", methods = "GET", metatype = true)
public class FooServlet extends SlingAllMethodsServlet {
..
protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) {
Session session = resourceResolver.adaptTo(Session.class);
Page currentPage = pageManager.getPage(request.getPathInfo());
String currentPagePath = currentPage.getPath();
...
}
My Question is: How to get the currentPagePath of the current Page in FooServlet? currentPagePath in the code is null.
As Thomas mentioned, if you define a servlet with fixed paths property, you wouldn't have reference to a Resource.
One way of achieving this is by passing your page path along with the request to the servlet. Also CQ.WCM.getPagePath() returns only /libs/wcm/core/content/siteadmin, as the current page is siteadmin and you may need to tweak your script a bit in order to access the selected page within siteadmin.
To get your page path either from siteadmin or from the page itself, you can use the following script and then pass the value to your servlet for further processing.
var currentPagePath = null;
/* if accessed via siteadmin */
if(CQ.wcm.SiteAdmin.hasListSelection()) {
var grid = CQ.wcm.SiteAdmin.getActiveGrid();
var selections = grid.getSelectionModel().getSelections();
/*Assuming that you are selecting only one page at a time. */
currentPagePath = selections[0].id;
} else { /* accessed via page */
currentPagePath = CQ.WCM.getPagePath();
}
And then you can call the servlet with the currentPagePath as one of the parameters.
GET /bin/fooServlet?currentPagePath=' + currentPagePath + '&foo=bar';
UPDATE
The above code works fine for CQ 5.5 + , for older versions you can use this.
var currentPagePath = null;
/* if accessed via siteadmin */
if(CQ.wcm.SiteAdmin.hasListSelection()) {
var grid = CQ.Ext.getCmp(window.CQ_SiteAdmin_id + "-grid");
if (grid) {
var selections = grid.getSelectionModel().getSelections();
currentPagePath = selections[0].id;
}
} else { /* accessed via page */
currentPagePath = CQ.WCM.getPagePath();
}
If you define the servlet with a fixed paths property you don't have any reference to a Resource or Page
You either need to define resourceTypes that matches to a page component or use cq:Page, but this will then be active for every request to a page and is not recommended without at least some selectors
Then you can get the Resource with request.getResource(). To get a Page you'll need to adapt the ResourceResolver to a PageManager and use getContainingPage(Resource resource).
Have a look at the documentation:
http://sling.apache.org/documentation/the-sling-engine/servlets.html
request.getPathInfo() in this case presumably is /bin/fooServlet?[parameterString], which is why PageManager is returning null for its path — from the PageManager's point of view, no resource exists at this location.
One simple option would be to send an additional callingPage parameter when hitting the Servlet. This way you could just read it from the parameter map:
GET /bin/fooServlet?foo=bar&callingPage=/en/home.html
void doGet() {
PageManager pageManager = resourceResolver.adaptTo(PageManager.class);
String callingPage = request.getParameter("callingPage");
String callingPagePath = pageManager.getPage(callingPage).getPath();
}
I don't know if it's a good pratice, but perhaps you could use the referer.
import java.net.URI;
import java.net.URISyntaxException;
try {
String currentPagePath = new URI(request.getHeader("referer")).getPath();
} catch (java.net.URISyntaxException e) {
}