I am currently diving into php and html and working on a simple redirect just for the purpose of showing database content through an url.
I know you can generate an URL in 2 ways, probably more but these two are the reason why I started this question:
php:
<?php
header('Location: example.php?parameter');
?>
html:
<form action="example.php" method="post">
<!--input fields etc -->
<input type="submit">
But now I was wondering "What is the best practice regarding these two options". Is it just a personal opinion with what you like the best and what is the best suitable way in a situation or is there something else I am overlooking.
I am not trying to start a discussion here, just interested in what is 'normally/commonly' used.
Thanks in advance!
These two pieces of code do fundamentally different things, even though in some cases the user-observed behavior may be very similar.
This is a server-initiated redirect:
<?php
header('Location: example.php?parameter');
?>
Basically this is the server's way of telling the browser that it should browse to another location. (The browser can ignore it, but doesn't really have a reason to ignore it.) Additional details can be added to the response to tell the browser if this redirection is temporary or permanent, or has other conditions regarding it. But at its simplest this is just the server saying "I don't really have anything for you here, go over there for your information."
This is a client-initiated form POST:
<form action="example.php" method="post">
Well, "client-initiated" in that the actual action of POSTing the form comes from the browser. The server probably gave that HTML tag to the client to tell it to do that, but the client is free to change it if it wants. (There's no reason to do so, though.) The point here is that this is a means by which the client sends data to example.php. It has nothing to do with redirects, it's just sending data to a specific resource on the server.
The server can respond to that data with a redirect, or a rendered page, or any other response.
These might be used in conjunction in a number of ways. Let's say you have page1.php and page2.php. On page1 there is a form, and after that form is submitted you want the user to see page2. This is where the user-observed result might be indistinguishable.
page1 can post to page2 and page2 can handle the submitted data and then display. Or page1 can post back to page1, handle the submitted data, and redirect to page2. To the end user, there's essentially no difference. The main difference is in how you organize your code. In that regard, sure, personal preference comes into play. But this isn't the only scenario in which either of these tools are employed. For example, you might want to submit values to a completely different page for a completely different reason, or redirect on a page request for some server-side reason completely unknown to the client.
As you develop more complex web applications you'll find certain patterns work well in certain situations, and personal preference will begin to conform to those patterns. In the end, these are just tools to perform actions (redirect the client to another location, send data to the server) and your overarching patterns and practices simply make use of the tools.
The HTTP location header and a HTML form are not really comparable.
The header should be used if you want to create a redirect during the execution of PHP. The form should be used if you want to submit user input from the client side (browser) to the server side.
HTML anchors are the best way to provide links on a web page:
Click
In most cases you use html forms or links. header() is used mainly if you want to redirect an user after the code is executed (e.g. after a successful login, or when is not authorized to access a restricted page)
Related
I am building a web app that contains a form. Currently, the user enters data into this form, which is saved in my database. Then the user opens a 3rd party website where it enters a subset of the exact same data into a form on that website.
Ideally, on submitting the form on my website, I would like to open the 3rd-party website in an iframe with its form prepopulated with the data already collected from my form. The obvious goal is to prevent the user from having to enter this same data twice, first on my form and second on the 3rd party form. Another benefit would be the lack of focus from my site as the user would need to complete additional steps after submitting the form on the 3rd party site.
I know that there are ways to prepopulate forms on other websites. For instance, Google Forms allows for forms to be prepopulated by passing values to the corresponding inputs' name attributes in a query string. Here's an example I created to demonstrate this (notice the query string.): https://docs.google.com/forms/d/e/1FAIpQLScqua9AJLvRgCuH8o-XfAGeZcbue9ND7a4z2JM5EcAuVqAwag/viewform?vc=0&c=0&w=1&entry.2020941857=Whatever+and+whatever&entry.473490210=foobar
Unfortunately, the "target" website does not appear to handle the incoming GET requests in a similar manner, which obviously should come as no surprise. Of course, it can't always be that easy. I can't even manipulate the values of the inputs in the target website's form by manipulating the DOM using Chrome DevTools (not that I would have any real understanding how that would help me even if I could).
Furthermore, the form doesn't even submit using an action attribute. Instead, here are the form and button elements that I admittedly don't understand (omitting some attributes for brevity's sake):
<form name="theForm" ng-submit="submitForm(theForm.$valid)"
no-submit-on-enter="" novalidate="">
<button class="btn btn-full ng-binding" type="submit" id="send-form"
track-event="{category: 'theFormSubmit', action: 'clicked'}"
skip-click-tracker=""> Submit </button>
</form>
I have also tried using DevTools to watch the headers as I submit information using the form. The headers don't appear to change when I click the button. In fact, there appears to be no activity at all in the Network tab when I click the button. I don't see any "Form Data" at all. But it's possible I'm misunderstanding what I'm seeing.
For what it's worth, it appears that the target relies heavily on Angular.js, which I know practically nothing about, so I'm not sure if its even relevant. I also am aware that iframes cannot be manipulated by javascript on my site unless it is of the same domain, which it is not. I briefly looked into phantom.js, but (from the little I understand) it appears that there would be an issue with maintaining the user's session on the target site. A reload would be required which would wipe out the prepopulated data defeating the entire purpose.
Anyway, I'm left wondering if there is some way to achieve my goal using PHP curl or really anything. As a side note, in case it is not already obvious: I do not have access to the full source code of the target website nor will I likely be able to obtain access to it.
UPDATE:
Using DevTools Network Tab, I again tried submitting the form with one of the inputs being the first name of Jude. I was finally able to isolate the header that contained the information by filtering by "Jude". The redacted header info and request URL are below:
I feel like I am finally getting somewhere. Based on the above, I feel that I might actually be able to submit the form data to the 3rd party website (sidestepping the actual entering and submitting of that website's form). Because I was using the UI, I could see that the form was submitted successfully, and I had visual cues for how that information was being dealt with. However, the HTTP 204 header (No Content) seems to indicate that if I send the information programmatically, there will be nothing returned for me to analyze success or failure of the form nor how the information is being dealt with. Ultimately, in the end, this may all be a red herring regardless because I am not sure how I would deal with the browser_session_id part of it anyway.
If you are using an iframe you might be out of luck, since browser cross origin policies will deny your JavaScript from tampering with the DOM in the IFRAME.
If the target website is simple enough, you can proxy over the whole form request and responses, cookies, and headers thorough your server (especially if you are using PHP) and then you are free from cross origin problams since the browser will see them as one origin
then you could access the iframes DOM
window.frames[0]...
or the anguler scope using
angular.element("#appname").scope()
I have a PHP form, and I'm wondering how I should handle submission. I remember when learning Rails that the behavior was to have a special handler page for a form, which then redirected the user to a landing page, which would prevent the user from accidentally re-submitting data by hitting the back button and going back to the form submission page.
For my PHP form, to avoid such errors (and for secureness, however it might play in) is it also best to send the form data via post to a handling page, which they redirects the user? Or would it be ok to just handle the form data on the same page as the form? If I did the latter, is it possible for a user to accidentally resubmit data via hitting back/refresh/etc?
Post-Redirect-Get is the design pattern recommended for web-forms to prevent resubmission (and what you used in rails)
It doesn't really matter if you submit to the same page or a different one, it's the redirect which prevents the accidental resubmission. You can therefore choose whether to post to the same page or a separate page depending on your coding style and/or application semantics.
The same principles apply to PHP. Redirection can help against accidental form refreshing. However, you still should take whatever precautions are necessary to avoid problems from accidental refreshing (e.g., using single use tokens, validating the input, etc).
I use my own MVC style of framework that simply has the dispatcher look for form posts on every page view and calls the appropriate controller that can process the request (assuming the submit-only-once requirements were met). It then redirects the browser to the appropriate landing page.
You can post to the same page, of course, but I think it will lead to bad practices, such as mixing too much logic, html, and database access together.
There's a third way to go about this that I am particularly fond of. In an effort to separate logic from presentation, I like to include a PHP file with every HTML document that requires processing of some kind (such as displaying dynamic data, handling HTTP POST requests etc.). I generally store this file in a separate directory and name it "filename.page.php". Needless to say, this is nothing more than a coding convention and you may want to call it something else.
In a sense, this means you're handling the HTTP POST request in the same file (at least as far as your web server is concerned). You can redirect clients anyway, though, by using the HTTP Location header like so:
header("Location: file.php")
As a side note, I wouldn't depend upon HTTP POST for security; it is no harder to make arbitrary HTTP POST requests than HTTP GET requests.
If a user tries to log in and the login fails the page should display an error message to the user. There are two main ways I see to do this: use a form action on the HTML page and in the php script if the login information is incorrect redirect with header to the login page with a $_GET value like loginfailed. The login page would check for this value and if it exists it would display the error.
The second way I see to do this is not use a form at all and instead use JQuery to capture the submit button press and use AJAX to determine if an error occurs. The php file would echo back a status and the javascript file would interpret it and if it was loginfailed, it would use JQuery to append the error message on to the page.
Now I will go over what I feel the pros and cons of each method are.
Method 1 Pros:
Very simplistic with no need for JQuery, Javascript, and AJAX.
The error status is displayed within the URL as well.
Method 1 Cons:
Since there is a header call, a redirect is necessary. Also, the login page must be reloaded. It is a small page but it is a reload nonetheless.
The status message is displayed in the URL. This means that users can type in status messages in to the URL and receive error messages on the page for errors that did not actually occur. Is this a problem? Maybe. Maybe not.
Method 2 Pros:
Since it is using AJAX, there is no need to load another URL and thus, no extra page is loaded.
This method uses JQuery to update the page with the error message so no redirect is necessary.
The error status is not displayed in the URL.
Method 2 Cons:
Much more complex than the first solution.
An external javascript file is needed and must be loaded every time the login page is accessed regardless of whether or not it is used.
The default behavior of the submit button is overridden and annulled. Its only behavior comes from its interaction with the javascript file.
What would SO do? I would like to stay away from answers such as "it depends on how much traffic your site would have" if that would be at all possible.
Always use the simplest solution possible until/unless there's a very good reason to do otherwise. It's better to finish something that's maybe (and maybe not) less than ideal than to deliver something gold-plated eventually, maybe.
Also, I generally prefer to follow a progressive enhancement strategy, such that everything works without Javascript, and then add Javascript to make it work in an improved manner. This has the added benefit of being functional, even when/where Javascript is disabled.
I think you fail to grasp the matter.
Login is not something self-sufficient. It is used to change state of the site. But with no reload it will not be changed. So, page reload is required anyway. or user will have to do it manually to get access to the authorized section.
Is login the only site feature that uses JQuery/AJAX? If not - why you're worrying about loading this library once, when most likely it will be loaded at every page?
There are still clients with JS disabled, for various reasons. A good web application will always let these clients in, even at cost of less functionality.
The latter is the main question, most important one. Why to choose between two? Why not to use both? - one for compatibility and another for usability?
So, I'd suggest to create basic functionality using GET to pass come codes, not messages.
And optionally improve it with some AJAX bells and whistles but with JS-based reload on succesful login anyway
I'm using PHP to data scrape another website. However, on certain occasions I need to confirm a variable (due to have two very alike possibilities).
The button I'm supposed to click to confirm my variable is:
<input type="submit" class="buttonEmphasized confirm_nl" name="start" value="Bevestig" accesskey="s" />
However, adding &start=Bevestig to the url doesn't seem to solve the problem, and I'm receiving the same page. What's more, is that the website is using sessions and every http_post_data seems to be starting a new session.
Is there a way to let PHP "click" a button if a certain output is missing?
This is a train time table data scraping system (using the HAFAS system).
Cheers
there is no generalized solution for this problem. every site is different in some way. your best bet is to analyze http message being sent by the original page. you can do it with firefox+firebug+live http headers for example. this way you're going to see all the parameters(required or not) and then replicate this message with your script.
it might(will, most likely) require faking session/cookie data. you might need to use curl for that.
If the post seems to be starting a new session, I would suspect that you are not respecting the cookies that were provided by the other side.
You need to send the session cookies back in the POST request.
That's also where you should be sending your start field. While many pages will accept parameters in URL or posted, they are not equivalent concepts.
"Is there a way to let PHP "click" a button if a certain output is missing?"
Nop, PHP is server-sided. Use Javascript
I have an application that supplies long list of parameters to a web page, so I have to use POST instead of GET. The problem is that when page gets displayed and user clicks the Back button, Firefox shows up a warning:
To display this page, Firefox must send information that will repeat any action (such as a search or order confirmation) that was performed earlier.
Since application is built in such way that going Back is a quite common operation, this is really annoying to end users.
Basically, I would like to do it the way this page does:
http://www.pikanya.net/testcache/
Enter something, submit, and click Back button. No warning, it just goes back.
Googling I found out that this might be a bug in Firefox 3, but I'd like to somehow get this behavior even after they "fix" it.
I guess it could be doable with some HTTP headers, but which exactly?
See my golden rule of web programming here:
Stop data inserting into a database twice
It says: “Never ever respond with a body to a POST-request. Always do the work, and then respond with a Location: header to redirect to the updated page so that browser requests it with GET”
If browser ever asks user about re-POST, your web app is broken. User should not ever see this question.
One way round it is to redirect the POST to a page which redirects to a GET - see Post/Redirect/Get on wikipedia.
Say your POST is 4K of form data. Presumably your server does something with that data rather than just displaying it once and throwing it away, such as saving it in a database. Keep doing that, or if it's a huge search form create a temporary copy of it in a database that gets purged after a few days or on a LRU basis when a space limit is used. Now create a representation of the data which can be accessed using GET. If it's temporary, generate an ID for it and use that as the URL; if it's a permanent set of data it probably has an ID or something that can be used for the URL. At the worst case, an algorithm like tiny url uses can collapse a big URL to a much smaller one. Redirect the POST to GET the representation of the data.
As a historical note, this technique was established practice in 1995.
One way to avoid that warning/behavior is to do the POST via AJAX, then send the user to another page (or not) separately.
I have been using the Session variable to help in this situation. Here's the method I use that has been working great for me for years:
//If there's something in the POST, move it to the session and then redirect right back to where we are
if ($_POST) {
$_SESSION['POST']=$_POST;
redirect($_SERVER["REQUEST_URI"]);
}
//If there's something in the SESSION POST, move it back to the POST and clear the SESSION POST
if ($_SESSION['POST']) {
$_POST=$_SESSION['POST'];
unset($_SESSION['POST']);
}
Technically you don't even need to put it back into a variable called $_POST. But it helps me in keeping track of what data has come from where.
I have an application that supplies long list of parameters to a web page, so I have to use POST instead of GET. The problem is that when page gets displayed and user clicks the Back button, Firefox shows up a warning:
Your reasoning is wrong. If the request is without side effects, it should be GET. If it has side effects, it should be POST. The choice should not be based on the number of parameters you need to pass.
As another solution you may stop to use redirecting at all.
You may process and render the processing result at once with no POST confirmation alert. You should just manipulate the browser history object:
history.replaceState("", "", "/the/result/page")
See full or short answers