Rest WS #Post consumes HttpServletRequest doesn't work - web-services

Here's my cxf Rest WS :
#POST
#OPTIONS
#Path("/push")
#Produces({ MediaType.APPLICATION_JSON })
#Consumes({ MediaType.APPLICATION_FORM_URLENCODED })
public Response push(#FormParam(value="agentId") String agentId);
I use it with a form :
<form id="form1" METHOD=POST ACTION="http://localhost:8080/uwv_interfacing-0.2.0-SNAPSHOT/api/rest/callHistory/push?AppKey=536f47d5-184f-3041-850c-bcad9f3afa49">
<input type="hidden" name="agentId" value="ofize">
<button type="submit" name="modifier" value="1">Submit</button>
</form>
I would like to get a HttpServletRequest instead of every fields, but when i replace "String agentId" with an HttpServletRequest it's empty, i have no fileds.
I've tried to replace the "#FormParam(value="agentId")" with "#Context" but i'm not sure about the good anotation to use.
Any idea?

You can inject MessageContext in your class like
import javax.ws.rs.core.Context;
import org.apache.cxf.jaxrs.ext.MessageContext;
...
#Context
private MessageContext messageContext;
...
// in your restful method, you could do something like
HttpServletRequest httpServletRequest = messageContext.getHttpServletRequest();

You can directly get the HttpServletRequest using #Context( qualified name: javax.ws.rs.core.Context) Hence your code shouls look like something as below.
#POST
#OPTIONS
#Path("/push")
#Produces({ MediaType.APPLICATION_JSON })
#Consumes({ MediaType.APPLICATION_FORM_URLENCODED })
public Response push(#FormParam(value="agentId") String agentId, final #Context HttpServletRequest request);

Related

How can I debug the request to detect why my HttpPost never fires?

Having the following HttpPost action
[AllowAnonymous]
[Route("api/Test")]
[ApiController]
public class TestController : ControllerBase
{
[Route("Something")]
[HttpPost]
//[IgnoreAntiforgeryToken]
public async Task<IActionResult> Something()
{
return Ok(new
{
Result = true
});
}
}
If I enable the [IgnoreAntiforgeryToken] tag, it works fine.
Then It seems that my post (from Postman) should sent the CSRF token, in that case:
I configure the __RequestVerificationToken (as a Header or as a Body with x-www-form-urlencoded)
Making sure that the token get updated
But I still get a 400
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "Bad Request",
"status": 400,
"traceId": "00-4b7d669686a083fbba09be86b6841e42-847918b0b6ca656b-00"
}
I tried to debug the request in order to discover what is happening?
public void Configure(IApplicationBuilder app)
{
app.Use(async (context, next) =>
{
var initialBody = context.Request.Body;
using (var bodyReader = new System.IO.StreamReader(context.Request.Body))
{
string body = await bodyReader.ReadToEndAsync();
Console.WriteLine(body);
context.Request.Body = new System.IO.MemoryStream(Encoding.UTF8.GetBytes(body));
await next.Invoke();
context.Request.Body = initialBody;
}
//await next.Invoke();
});
}
But I haven't found anything special.
How can I find out what is generating this 400 Bad Request?
You may misunderstand what is the process of testing endpoints protected with an XSRF token in Postman.
Pre-request script to set the value of the xsrf-token environment variable. And from the script, you need be sure the {url} you called is a view which contains input with name="__RequestVerificationToken".
Then you send post request to the api/test.
Here is my working code:
1.Index.cshtml:
<form method="post">
//if it does not generate the token by default
//you can manually add:
//#Html.AntiForgeryToken()
</form>
2.Set the environment:
VARIABLE
INITIALVALUE
member-url
https://localhost:portNumber
xsrf-token
3.Be sure apply the enviroment:
4.Pre-request script:
5.API:
[Route("Something")]
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Something()
{
return Ok(new
{
Result = true
});
}
After you get 200 response, you can see the token value in your created environment.

Angular2 How to POST data using a service class

I have a simple application form which I am trying to post to the server. I am fairly new to Angular2
How can I pass the data from the component to the service and onto the server for a POST request.
The POST is working fine when I try it directly from FireFox plugin 'httpRequester'
This is the TaskComponent.ts
#Component({
selector: 'tasks',
template: `<div mdl class="mdl-grid demo-content">
<div class="demo-graphs mdl-shadow--2dp mdl-color--white mdl-cell mdl-cell--8-col">
<h3>Create Task Page</h3>
<form action="#" (ngSubmit)="onSubmit()">
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input class="mdl-textfield__input" type="text" pattern="[A-Z,a-z]*" id="taskname" [(ngModel)]="data.taskname"/>
<label class="mdl-textfield__label" for="taskname">Task Name</label>
<span class="mdl-textfield__error">Only alphabet and no spaces, please!</span>
</div>
<button class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored" type="submit">Create Task</button>
</form>
`,
directives: [ROUTER_DIRECTIVES, MDL]
})
export class CreateTaskComponent {
data: any
constructor() {
this.data = {
//taskname: 'Example Task'
};
}
onSubmit(form) {
console.log(this.data.taskname); <--Data is passed upon submit onto the console. Works fine.
//Need to call the postApartment method of ApartmentService
}
}
ApartmentService.ts
import {Http, Response} from 'angular2/http'
import {Injectable} from 'angular2/core'
import 'rxjs/add/operator/map';
#Injectable()
export class ApartmentService {
http: Http;
constructor(http: Http) {
this.http = http;
}
getEntries() {
return this.http.get('./api/apartments').map((res: Response) => res.json());
}
getProfile(userEmail :string){
return this.http.get(`./api/apartments/getprofile/${userEmail}`).map((res: Response) => res.json());
}
postApartment(){
// Not familiar with the syntax here
}
}
Server.ts
router.route('/api/apartments')
.post(function(req, res) {
var apartment = new Apartment();
apartment.name = req.body.name;
apartment.save(function(err) {
if (err)
res.send(err);
res.json({ message: 'Apartment created!' });
});
})
You can inject service via dependency injection and use it in the component
export class CreateTaskComponent {
constructor(){private _apartmentService: ApartmentService}{}
}
And you can access this in any of the component function via
onSubmit(form) {
console.log(this.data.taskname); <--Data is passed upon submit onto the console. Works fine.
//Need to call the postApartment method of ApartmentService
this._apartmentService.postApartment()
}
And when bootstraping the component you have to add it as dependency via
bootstrap(AppComponent, [ApartmentService]);
Another option for doing the last step is by added providers in the Component decorator like
#Component{
providers: [ApartmentService]
}
Inject the apartmentService in the component, No need of providers as I have bootstrapped it. (If you bootstartp the service, Do not include it in providers. It breaks the system)
export class CreateTaskComponent {
data: any
constructor(private apartmentService: ApartmentService) {
this.data = {};
}
onSubmit(form) {
this.apartmentService.postApartment(this.data);
}
}
The critical piece is the postApartment() method in the service
postApartment(data :any){
return this.http.post('/api/apartments',
JSON.stringify(data),{headers : new Headers({'Content-Type':'application/json'})
})
.map((res: Response) => res.json()).subscribe();
}
Also make sure on the server.js code, the mongoose fields match the http body parameters being passed.
I had to fix it to make it work.

ember-cli-mirage testing request params

I have default params that are added to the search request from a route. I would like to test these in ember-cli-mirage but am stuck on how to capture the request or requestBody so that I can assert against it.
Was looking for something similar to what I found on this SO post, but need access to the actual request and not the DOM. I am able to access the search params entered by the user (the 'text' param in my example) using currentUrl(), but the default params included in the request sent to the server, but not the url.
Is there a way to capture and assert against the request itself using ember-cli-mirage?
Something like
test('it appends default params to request'), function(assert) {
let searchUrl = '/my/route/url';
server.get(searchUrl, (db, request) => {
assert.equal(request.requestBody, "text=abc&all=true");
}
});
EDIT
I was able to get the test to pass using Qunit's async helper, like so:
test('it appends default params to athlete request', function(assert) {
assert.expect(2);
let done = assert.async();
server.get('/athletes', (db, request) => {
let params = request.queryParams;
assert.equal(params["page"], "1");
assert.equal(params["per"], "50");
done();
});
server.create('athlete', {first_name: 'John'});
visit('/athletes');
});
Still getting an error in the console for this test related to the json:api serialization:
normalizeResponse must return a valid JSON API document:
* meta must be an object
Going to open another question related to this failure elsewhere and link it in the comments.
The request param passed to your route handlers is the PretenderJS request object, which has some useful keys:
request.params, the dynamic segments of your route
request.queryParams, deserialized query request params
request.requestBody, the text body, You can use JSON.parse(request.requestBody) to turn this into an object.
So, if you wanted to assert against the query params, use request.queryParms.

Struts 1.3: when is better to use DispatchActions than Action?

In what cases is better to use DispatchActions than Action?
When you need many similar actions with similar form bean in the same struts module (e.g. CRUD actions to create read update delete the same object). With plain Action you'll need 4 Struts action files with imports, headers, method signatures:
// CreateAction.java
package com.example.package;
// imports and header
public class CreateAction extends Action {
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
// actual code
}
}
// ReadAction.java
package com.example.package;
// imports and header
public class ReadAction extends Action {
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
// actual code
}
}
// UpdateAction.java
package com.example.package;
// imports and header
public class UpdateAction extends Action {
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
// actual code
}
}
// DeleteAction.java
package com.example.package;
// imports and header
public class DeleteAction extends Action {
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
// actual code
}
}
Also you'll need 4 action mappings in struts-config.xml (of course if you are not using annotations). But in fact they will just invoke the next layer of code (manager/DAO/etc), which is independent from web (from request/response/mapping classes) and thus testable with unit tests allowing test-driven development and code reusability. All four classes will differ only in 1-2 lines of code. The rest is boilerplate, repeating again and again.
By adding additional parameters or reusing existing one in HTTP request (in other words: in JSP form tag) you can pack all 4 actions in one class, e.g. in EventDispatchAction:
// CRUDAction.java
package com.example.package;
// imports and header
public class CRUDAction extends EventDispatchAction {
public ActionForward create(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
// actual code
}
public ActionForward read(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
// actual code
}
public ActionForward update(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
// actual code
}
public ActionForward delete(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
// actual code
}
}
This requires much less boilerplate. In order to tell which action you want to perform, you can use submit buttons:
<html:submit property="update" value="Save" />
<html:submit property="delete" value="Delete" />

Proper signature for collection postback?

I haven an entity with a collection, something like: Product.Parts - when I render a view for Product, I call .EditorFor(x => x.Parts), which names my fields like: Parts[0].Name.
how do I declare my controller method that receives the postback so it can recompose those field names into something useful?
I originally tried:
[HttpPost] public ActionResult Create(Product entity)
which seemed to give me an object of the right type but was all empty (properties were null). then I tried:
[HttpPost] public ActionResult Create(List<Product> entity)
but in this case entity itself is null. also, this didn't help:
[HttpPost] public ActionResult Create(IList entity)
I guess I can always do this:
[HttpPost] public ActionResult Create(FormCollection form)
{
var Name = form["Product[0].Name"];
}
but that's eecky! help?
your 1st attempt should have worked... maybe have a look at the posted values in firefox or chrome?