grails form redirect gives 404, but url mapping works - forms

I feel like I've entered the Twilight Zone. I have a Grails form that redirects to a URL, but gives a 404. If I go directly to that exact URL, everything works fine (that is, the URL mappings are correct).
This is an example generated form tag:
<form action="/alm/contactRefresh/itemRefreshProcess/7070" method="post">
On submit, it redirects to:
http://localhost:8080/alm/contactRefresh/itemRefreshProcess/7070
But gives this error:
HTTP ERROR 404
Problem accessing /alm/contactRefresh/itemRefreshProcess/7070. Reason:
NOT_FOUND
Powered by Jetty://
But then if I just go directly to that same URL (by focusing the browser Location bar and pressing enter), the page renders just fine, though the form params are lost because it's just a GET now. I've also tried changing the form method to GET, and that doesn't work either (throws a 404).
I've done similar forms a zillion times before with no problems. I'm sure this is some stupid user error, but I seriously can't figure out what's wrong.
Thanks for any ideas!

So, I finally started ripping parts out of the form and found out that for some reason you can’t name a Grails checkbox starting with the word "action". It must be something related to the default params["action"] entry. Though my checkbox names were a concatenation of "action_" + an id.
Anyway, there was some kind pre-processing of the checkbox form params that was blowing up before making it to the controller, and somehow that translated to a 404 instead of an actual Exception.
Originally I had this:
<g:checkBox name="action_${serviceRefreshAction.id}" value="${true}" />
Which renders this:
<input type="hidden" name="_action_7196" /><input type="checkbox" name="action_7196" checked="checked" id="action_7196" />
I changed "action" to "myAction", like this:
<g:checkBox name="myAction_${serviceRefreshAction.id}" value="${true}" />
Which renders this:
<input type="hidden" name="_myAction_7206" /><input type="checkbox" name="myAction_7206" checked="checked" id="myAction_7206" />
And now everything works fine.
Five hours of my life down the drain.
But I guess I have to forgive Grails, for the all time it saves me on a daily basis normally. :o)

Related

Gorilla CSRF - Forbidden - CSRF token invalid - fails when there are two forms

I'm adding in CSRF token validation and I'm running into a problem where I have two forms on a page and one of them will submit successfully and the other will not. I'm not doing AJAX requests, I'm simply using hidden input fields. If I submit the form when it is the only one on the page, it submits without issue. If I submit it on a page with more than one form, it fails.
Below is the template code for my two forms
{{if .IsAuthenticated}}
<form action='/admin/logout' method='POST'>
<button>Logout</button>
{{.CsrfField}}
</form>
{{end}}
<form action='/admin/stuff/create' method='POST'>
{{with .Form}}
<div>
<label>Title:</label>
<input type='text' name='title' value='{{.Get "title"}}'>
</div>
<div>
<input type='submit' value='Publish stuff'>
</div>
{{end}}
{{.CsrfField}}
</form>
And this is what the generated HTML looks like. Both appear to be valid.
When I click the "Logout" button though, I get the Forbidden - CSRF token invalid error, but clicking the create input value in the second form always works.
The logout button is correctly validated when I attempt to use it on the home page which is "/admin/" but it does not work on any of the other pages "/admin/snippet/:id" or "/admin/snippet/create". The Logout button is part of a base template, so it appears on every page, so there shouldn't be anything different in how it appears on any page.
I've read other SO posts about multiple forms & CSRF tokens on a page and I understand there should be no issue with multiple forms with the same information as long as you have each one in it's own form, it should be fine. So I am not sure where I am going wrong.
I found the issue. Currently the way that gorilla/csrf works, it does not like creating the masked token from one path and then sending that token off to another path. So in my situation, going from /admin/snippet/create to /admin/logout threw an error because it was expecting the path for the token to be /admin/snippet/<something> and so it threw an error.
This issue has been addressed in this PR: https://github.com/gorilla/csrf/pull/147 and essentially the solution is to set the default path yourself to something which all of your routes will contain, so in my case that was /admin
This is what my CSRF declaration looks like now in main.go
var csrfMiddleWare = csrf.Protect(
[]byte("<put your 32 character key here>"),
csrf.Path("/admin"),
csrf.Secure(false),
)
A note, if you had this issue and then apply this fix and it doesn't resolve the problem, trying testing in a separate browser as there may be some caching issues.

Can i use ngxErrors or something like it to display a form error?

I use ngxErrors to display errors for a form control and it works great. Is there any way to get similar functionality for a form or a form group? Currently, I display a form error like this:
<div *ngIf="form.hasError('loginFailed')">
Login Failed
</div>
The bummer is, when I detect that there is a form error (e.g. after the login form is submitted) as opposed to control error, I set it like this:
this.form.setErrors({ loginFailed: true });
this.cdr.detectChanges();
Where this.cdr is an instance of ChangeDetectorRef. This is necessary because I'm using OnPush change detection strategy. So basically it's like calling $scope.$apply() from AngularJS all over again.
What I would really like to do is something more like how ngxErrors does it:
<div ngxErrors="myForm">
<div ngxError="loginFailed" [when]="['dirty', 'touched']">
The login has failed
</div>
But ngxErrors expects myForm to be a control.
This feature is not currently baked into ngxErrors, but I submitted a PR. https://github.com/UltimateAngular/ngxerrors/pull/18
The working syntax is a slight modification of the above:
<div ngxErrors>
<div ngxError="loginFailed" [when]="['dirty', 'touched']">
The login has failed
</div>
</div>
I learned that you do not have to tell child components the form, the FormGroupDirective is available to children automatically.
See this library https://www.npmjs.com/package/ng-error-messages for show error messages based on validation rules:
<input placeholder="Texto:" formControlName="text">
<div errorMessage="text" alias="Super Texto" ></div>

IE form action URL issue

Recently i am started tuning our products to IE compatability. Now i am facing a weird problem in IE alone.
My form url is something like this https://x.com/formurl/dynamicvalue
and my form element is
<form action="" method='post'>
...
</form>
some values the dynamicvalue holds are ( Alphanumeric characters )
plan
plan2
1234443
544
Except IE every other browsers sending the actions to https://x.com/formurl/dynamicvalue
IE form action is sending to https://x.com/formurl
I don't know why this is happening, I can replace the document.URL to post the Form back to solve the problem. Still, i want to what's the reason for IE to remove that dynamicvalue
I am testing in IE-9
Kindly someone teach me.
Thanks in advance.
I have also discovered this bug in Internet Explorer 11 when reading the action attribute of a form with action set to the empty string.
<form action="" method="post"></form>
If one reads the form.action attribute in javascript and the current URL does not contain a trailing slash, the last part of the URL will be removed. I.e., if the location is example.com/xxx/yyy, form.action=="example.com/xxx, while if location is example.com/xxx/yyy/, form.action=="example.com/xxx/yyy/.
However, if the form is posted by clicking a submit button, it is posted to the correct URL, i.e., example.com/xxx/yyy or example.com/xxx/yyy/.
I overcame this by using jQuery's attr function to check if action="" in the HTML and then I use location.href instead.
if($(form).attr('action') === '') return location.href else return $(form).attr('action')
(Why would someone do this? I am intercepting the form submit and using ajax to send the data. To do this, I need to know where the form wants to submit)

How to add a contact form to a static web site?

I have a mostly "static" web site with no server-side code and just a little JavaScript. Now I would like to add a contact form. I do not care how I get the contact form data (so just writing this data to a text file in the server will be ok).
What is the simplest solution for this problem? How do people usually handle this?
I believe I can add some server-side code (PHP or something) to handle the form (and write the form data to a file, for instance) but I would prefer a client-side solution.
Use an external tool, they are commonly referred to as "formmailer". You basically submit the form to their server, and they send the form contents via mail to you.
If you don't want that, you have to do something server-sided: Storing data on the server, without having a server side program that accepts the data from the client, is just not possible.
You could install CouchDB and interface that from Javascript :) Everyone could use that then, too :)
The most easy PHP script that stores POST data on your harddisk:
<?php file_put_contents('/path/to/file', serialize($_POST) . "\n", FILE_APPEND); ?>
You can use Google Drive and create form with required fields. and embed code (which will be iframe) in your static web page.
You will be able to get submitted data in spreadsheet.
You can use qontacto . it is a free contact form you can add to any website. it forwards you the messages.
I set up the fwdform service for this exact need.
Just two simple steps to get your form forwarded to your email.
1.Register
Make an HTTP POST request to register your email.
$ curl --data "email=<your_email>" https://fwdform.herokuapp.com/register
Token: 780a8c9b-dc2d-4258-83af-4deefe446dee
2. Set up your form
<form action="https://fwdform.herokuapp.com/user/<token>" method="post">
Email: <input type="text" name="name"><br>
Name: <input type="text" name="email"><br>
Message: <textarea name="message" cols="40" rows="5"></textarea>
<input type="submit" value="Send Message">
</form>
With a couple of extra seconds you can spin up your own instance on Heroku.

Sinatra execute code before uploading

I'm having a simple HTML form on my page that looks like this:
<form action="/" method="post" enctype="multipart/form-data">
<input type="file" name="file" />
<input type="input" name="pin" />
<input type="submit" value="Upload" />
</form>
Now what I am trying to accomplish (with Sinatra) is to check if the PIN entered into the form field is correct:
post "/" do
if params[:pin] == "1234"
start_upload()
else
print_error_message()
end
end
Of course, I want the PIN to be checked before the file starts uploading. But that's my problem. Immediately after clicking the "Upload" button, the file upload starts until it is finished. Then the script checks to see if the PIN is valid.
Is there a way to do stuff before the file upload starts? And if not, what other ways of doing this are there?
Unless you use some Ajax and split up your request this won't work. You could have two forms, one that holds the pin and that authorizes the user. Once you enter a correct pin you send an asyn request to the server which will then reply with a positive or a negative answer. Depending on the response some javascript will then enable your file upload button so you can start uploading the file. What you should also do is setting a session for the user so that only an authorized user (via the pin) is allowed to send a form. If you check the Sinatra Readme you can find some information on how to do that.
That would be my solution.