Laravel CSRF token empty in AJAX-rendered content - laravel-5

"laravel/framework": "5.4.*",
"laravelcollective/html": "^5.4",
I have a view partial that contains delete buttons, and is rendered both normally and through AJAX requests. After the latter, the forms for these buttons are not getting the CSRF token when the partial is rendered. The hidden input value is empty, resulting in a TokenMismatchException when they are subsequently used
Note that the forms for these buttons DO NOT use AJAX. My problem has nothing to do with telling javascript to fetch the token from the meta tag and include it in an AJAX request. That works fine. These forms are being submitted with a normal, old-school request. (When the page reloads after delete the content is loaded at the correct page.)
The pagination request that results in the new partial being rendered goes to a controller in API namespace. Thus, i tried adding the "web" middleware to the route in api.php:
Route::middleware(['auth:api', 'web']) ...
This did cause the token value to show up in the delete forms. However, and as i was pretty sure would happen, it does not match the one that had previously been set in the meta tag.
The token is passed to FormBuilder's constructor. Is there something that i can do in the controller (on the pagination request) to pass the token to View, such that it ends up being passed to FormBuilder before the partial is rendered? (I'm not clear on where/when FormBuilder is instantiated.)
Another idea might be to include the token in the pagination request, pass it from the controller as a view variable, and manually create the token input. (With some logic to only do it for ajax requests.)
That seems hacky, though. I want to think on that a bit further before pursuing it, and was hoping someone might have an idea of how to achieve the former (or a better) solution.

A very simple solution occurred to me, although it's not specific to Laravel. What I can do is have the pagination component get the token from the meta tag, then check the incoming html fragments for the presence of any _token hidden fields and apply the value as needed.

Related

Laravel Redirect as POST

Currently my users must get the visit form given by Route::get then fill it in to get back a result view given by Route::post. I need to create a shareable link such as /account/search/vrm/{vrm} where {vrm} is the VRM that is usually filled in on the form page. This VRM then needs to redirected to Route::post as post data. This needs to be done by my controller. How can I do this in my controller?
Routes:
// Shows form view
Route::get('/account/search', 'User\AccountController#getSearch')->name('account.search');
// Shows result view
Route::post('/account/search', 'User\AccountController#runSearch');
// Redirect to /account/search as POST
Route::get('/account/search/vrm/{vrm}', function($vrm) { ???????? });
POSTs cannot be redirected.
Your best bet is to have them land on a page that contains a form with <input type="hidden"> fields and some JavaScript that immediately re-submits it to the desired destination.
You can redirect to a controller action or call the controller directly, see the answer here:
In summary, setting the request method in the controller, or calling a controller's action.
Ps: I don't want to repeat the same thing.
For those who comes later:
If you are using blade templating engine for the views, you can add '#csrf' blade directive after the form starting tag to prevent this. This is done by laravel to prevent cross site reference attacks. By adding this directive, you can get around this.
return redirect()->route('YOUR_ROUTE',['PARAM'=>'VARIABLE'])

jquery ajax search form

I have a REST Url http://localhost/issues presenting me a search form for querying issues of a bug tracker system. The search form has a textfield with name="f". The action of the form is action="/issues" and the method=GET. So if I type "foobar" into the textfield, I am getting redirected to http://localhost/issues?f=foobar.
To prevent page reload, I use AJAX with jquery. So I used $(document).on('submit',...) to bind an AJAX query function to the submit function of the form. I used firebug to proove, that jquery sends the request and no page reload is taken. I also have a function to fill results of the response into my site presented in the browser. Everything works fine for the first search attempt.
But if I type another search string "anotherfoobar" into the textfield and resend the request, the request URL is http://localhost/issues?f=foobar&f=anotherfoobar, so the search parameter is only appended to the URL, not updatedas I thought it would happen.
I've read about "hashing" the URL parameters to prevent this behaviour here on stackoverflow, but do not fully understand what and why this is happening and what "hashing" means exactly. Perhaps it's not the right solution for me. So I kindly ask someone to explain me how I can solve this.
I've solved it! Don't ask how exactly, what I did was the following:
The AJAX response is the whole Web page as I would get it with a page reload. with jquery I select a div which includes the search form AND the results.
I simply defined a div only for the results, and update only the content of the results div. After doing so, everything works fine, and the results div updates with multiple search attempts.
Another case of not knowing what I do, but I do it fine ;)
Perhaps someone still can explain me my error so wisdom can rise.

Sinatra + Ajax to load dynamic content

I want to create a page with will be filled with dynamic info using Ajax (JQuery). The info will come from various GETs I need to do in other URLs.
I'll be using Sinatra + JQuery to to that, but as my WEB experience is almost null and don't have any idea how do to it right.
The requisites for this are:
Each time a GET completes, a new line of information should appear on the page.
If the GET could not be complete, a default info appear on the page.
My idea so far is to do something like this:
Have my controller performing each GET inside a thread.
Each time a thread ends, with success or not, I inform the view of the result and render a partial
I'll have as many partial as I need (for each GET I must do)
The first time I load the page I fill in the default info, them I update via AJAX with the successful GET responses
This does not seem the correct approach, so I'm asking someone that already did something similar or has more experience on this some help.
You start off with a simple get('/'){} route that holds the default message (or any other GET route). Then you have your other GET routes that you want to display on your default route. In Sinatra you can check whether a request is an xhr-request or not with a request.xhr? If you have an xhr request you return a json value to your view, otherwise reject the request or render a view with proper html. This is on your sinatra backend. In your views you can use JQuery or any other JS library or plain JS to handle asynchronous data requests. You can use the ajax function in JQuery to request data from your routes and then add them to your DOM. It's as simple as that :)
Now you will have to investigate on the JQuery site how to make ajax requests and how to append data to existing DOMs. That's all there is to it.

Codeigniter AJAX and POST

What is the best way to address an AJAX script that sends data to POST in codeigniter? Right now I am loading a view with the AJAX through $this->load->view('AJAX', $data); however there is no UI or user actions in the view. It's simply running through the script and returning POST data a little after the script loads. I receive the POST data in my model where I input the values into the DB and output some other values based on the data.
I need to open a real view, set metatags and re-direct the user to another website afterwards.
How do I address this?
The problem I'm facing is that I cannot open up another view because the AJAX view is the one that's in focus but I need this AJAX view to be temporary that basically does it's thing and sends to POST.
Is there any convention that I can lookup/research to what I'm describing? Let me know what kind of clarification is needed if any.
Some people like to write "ajax" controllers and post to them exclusively, but you don't need to do that. You can handle the request in the same controller that handles the non-ajax request. Personally, I exclusively return json, but you can return chunks of HTML if that works better for you.
Your exact problem is vague (actual code would help clarify), but I think you are on the wrong track. Don't use a view for processing anything ever. Use your Controller layer, this is for handling input and requests.
Example of controller method responding to either ajax or non-ajax request:
function edit_user()
{
$data['status'] = $this->user_model->save();
if ($this->input->is_ajax_request())
{
// return json string with our update status
// Something like: {"status":true}
echo json_encode($data);
exit;
}
// Load the non ajax view with the same data
$this->load->view('users/edit', $data)
}
$this->input->is_ajax_request() is a function of the Input class that reads $_SERVER['HTTP_X_REQUESTED_WITH'] and checks if it's value is XMLHttpRequest. This should only be true if it's an "ajax" request.
You can make life easier by wrapping this in a class or function. No matter what you decide to do, don't use the view layer for processing data.
I think my problem is, how do I address javascript without a view? how do I call the script and/or where do I put the JS code in the controller? I felt it was the wrong direction to address the code in a view but I didn't see how else to do it.
Whenever possible, you should put javascript code in a .js file and use a <script> tag to load it, in an HTML document. The only other exception is putting it in a "view" file (a file that's only purpose is to construct your final HTML output). In other words, follow the same rules of HTML as to where to put javascript, and follow the usual conventions of MVC of where HTML belongs (in the view). Javascript code does not belong in your controller. Javascript is not processing your data, it is sending the data to the server.
I need to open a real view, set metatags and re-direct the user to another website afterwards.
If you want to load a view, then redirect (after a certain amount of time I assume), you can do it with javascript or a <meta> tag (but don't use a meta tag, use js).

How can I add a URL parameter but hide others in a POST - Spring MVC

I'm trying to add a URL parameter within a Spring MVC application. It's a basic search page that shows results.
In the search page, there is a form that is set to POST. There are many hidden fields and other fields I don't want in the URL. So, I don't want to do a GET.
I do want the search query in the URL. So after clicking the search button, the resulting search results page needs to have a URL like /search?query=hello
To get it to work, I'm creating a RequestMapping method in the Spring MVC Controller and doing a redirect: tacking on the query parameter. However, I'm not sure using a redirect is the best answer, seems there could be performance concerns redirecting as well.
I looked around and noticed folks using javascript and the location object, but setting the location object obviously relaunches the URL you set it to. I also looked at the HTTPServletResponse & HTTPServletRequest objects, but couldn't find much.
Any thoughts on how I can force the search parameter to be added to the URL?
Your form will have an 'action' specified telling it where to POST to. I'd have thought you could attach an onclick event to your submit button (or an onsubmit event to your form) that updates the action url by appending "?query=" to it.
document.<form name>.action += "?query=...";
Then you just have to worry about someone posting your form without JavaScript enabled - in this case you could fall back to your redirect.
I don't know how the server technology so I can't say if it will be happy giving you both GET and POST parameters, if not you'll have to manually strip the GETs out of the URL.
But anyway, this seems like a rather odd situation to be in - is it really that big a deal to show the parameters in the URL? Anything that gets posted by an HTML form can still be inspected with the right tools, it's just ever so slightly more difficult.
I wanted to provide a more complete answer to my question with code. The previous user helped me down this path, so I'll keep it as the accepted answer. However, there is one item to note:
If you add on to the action, and you have an input text box with the same name, the page posts a duplicate value like: query=hello,hello.
So, I needed to remove the name on the input box, and use the following javascript. Note, I am using the prototype.js framework:
Event.observe(window, 'load', function(event) {
Event.observe('searchForm', 'submit', function(event) {
$('searchForm').action += "?query="+$('searchBox').value;
});

Resources