Sending form data

Once the form data has been validated on the client-side, it is okay to submit the form. And, since we covered validation in the previous article, we're ready to submit! This article looks at what happens when a user submits a form — where does the data go, and how do we handle it when it gets there? We also look at some of the security concerns associated with sending form data.

Prerequisites: Basic computer literacy, an understanding of HTML , and basic knowledge of HTTP and server-side programming .
Objective: To understand what happens when form data is submitted, including getting a basic idea of how data is processed on the server.

First we'll discuss what happens to the data when a form is submitted.

Client/server architecture

At its most basic, the web uses a client/server architecture that can be summarized as follows: a client (usually a web browser) sends a request to a server (most of the time a web server like Apache , Nginx , IIS , Tomcat , etc.), using the HTTP protocol . The server answers the request using the same protocol.

A basic schema of the Web client/server architecture

An HTML form on a web page is nothing more than a convenient user-friendly way to configure an HTTP request to send data to a server. This enables the user to provide information to be delivered in the HTTP request.

注意: To get a better idea of how client-server architectures work, read our Server-side website programming first steps 模块。

On the client side: defining how to send the data

<form> element defines how the data will be sent. All of its attributes are designed to let you configure the request to be sent when a user hits a submit button. The two most important attributes are action and 方法 .

The action attribute

action attribute defines where the data gets sent. Its value must be a valid relative or absolute URL . If this attribute isn't provided, the data will be sent to the URL of the page containing the form — the current page.

In this example, the data is sent to an absolute URL — https://example.com :

<form action="https://example.com">

					

Here, we use a relative URL — the data is sent to a different URL on the same origin:

<form action="/somewhere_else">

					

When specified with no attributes, as below, the <form> data is sent to the same page that the form is present on:

<form>

					

注意: It's possible to specify a URL that uses the HTTPS (secure HTTP) protocol. When you do this, the data is encrypted along with the rest of the request, even if the form itself is hosted on an insecure page accessed using HTTP. On the other hand, if the form is hosted on a secure page but you specify an insecure HTTP URL with the action attribute, all browsers display a security warning to the user each time they try to send data because the data will not be encrypted.

The names and values of the non-file form controls are sent to the server as name=value pairs joined with ampersands. The action value should be a file on the server that can handle the incoming data, including ensuring server-side validation. The server then responds, generally handling the data and loading the URL defined by the action attribute, causing a new page load (or a refresh of the existing page, if the action points to the same page).

How the data is sent depends on the 方法 属性。

The method attribute

方法 attribute defines how data is sent. The HTTP protocol provides several ways to perform a request; HTML form data can be transmitted via a number of different methods, the most common being the GET 方法和 POST 方法

To understand the difference between those two methods, let's step back and examine how HTTP works . Each time you want to reach a resource on the Web, the browser sends a request to a URL. An HTTP request consists of two parts: a header that contains a set of global metadata about the browser's capabilities, and a body that can contain information necessary for the server to process the specific request.

The GET method

GET 方法 is the method used by the browser to ask the server to send back a given resource: "Hey server, I want to get this resource." In this case, the browser sends an empty body. Because the body is empty, if a form is sent using this method the data sent to the server is appended to the URL.

Consider the following form:

<form action="http://www.foo.com" method="GET">
  <div>
    <label for="say">What greeting do you want to say?</label>
    <input name="say" id="say" value="Hi">
  </div>
  <div>
    <label for="to">Who do you want to say it to?</label>
    <input name="to" id="to" value="Mom">
  </div>
  <div>
    <button>Send my greetings</button>
  </div>
</form>

					

由于 GET method has been used, you'll see the URL www.foo.com/?say=Hi&to=Mom appear in the browser address bar when you submit the form.

The data is appended to the URL as a series of name/value pairs. After the URL web address has ended, we include a question mark ( ? ) followed by the name/value pairs, each one separated by an ampersand ( & ). In this case we are passing two pieces of data to the server:

  • say , which has a value of Hi
  • to , which has a value of Mom

The HTTP request looks like this:

GET /?say=Hi&to=Mom HTTP/2.0
Host: foo.com
					

注意: You can find this example on GitHub — see get-method.html ( see it live also ).

The POST method

POST 方法 is a little different. It's the method the browser uses to talk to the server when asking for a response that takes into account the data provided in the body of the HTTP request: "Hey server, take a look at this data and send me back an appropriate result." If a form is sent using this method, the data is appended to the body of the HTTP request.

Let's look at an example — this is the same form we looked at in the GET section above, but with the 方法 属性设置为 POST .

<form action="http://www.foo.com" method="POST">
  <div>
    <label for="say">What greeting do you want to say?</label>
    <input name="say" id="say" value="Hi">
  </div>
  <div>
    <label for="to">Who do you want to say it to?</label>
    <input name="to" id="to" value="Mom">
  </div>
  <div>
    <button>Send my greetings</button>
  </div>
</form>

					

When the form is submitted using the POST method, you get no data appended to the URL, and the HTTP request looks like so, with the data included in the request body instead:

POST / HTTP/2.0
Host: foo.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 13
say=Hi&to=Mom
					

Content-Length header indicates the size of the body, and the Content-Type header indicates the type of resource sent to the server. We'll discuss these headers later on.

注意: You can find this example on GitHub — see post-method.html ( see it live also ).

Viewing HTTP requests

HTTP requests are never displayed to the user (if you want to see them, you need to use tools such as the Firefox Network Monitor Chrome Developer Tools ). As an example, your form data will be shown as follows in the Chrome Network tab. After submitting the form:

  1. Open the developer tools.
  2. Select "Network"
  3. Select "All"
  4. Select "foo.com" in the "Name" tab
  5. Select "Headers"

You can then get the form data, as shown in the image below.

The only thing displayed to the user is the URL called. As we mentioned above, with a GET request the user will see the data in their URL bar, but with a POST request they won't. This can be very important for two reasons:

  1. If you need to send a password (or any other sensitive piece of data), never use the GET method or you risk displaying it in the URL bar, which would be very insecure.
  2. If you need to send a large amount of data, the POST method is preferred because some browsers limit the sizes of URLs. In addition, many servers limit the length of URLs they accept.

On the server side: retrieving the data

Whichever HTTP method you choose, the server receives a string that will be parsed in order to get the data as a list of key/value pairs. The way you access this list depends on the development platform you use and on any specific frameworks you may be using with it.

Example: Raw PHP

PHP offers some global objects to access the data. Assuming you've used the POST method, the following example just takes the data and displays it to the user. Of course, what you do with the data is up to you. You might display it, store it into a database, send it by email, or process it in some other way.

<?php
  // The global $_POST variable allows you to access the data sent with the POST method by name
  // To access the data sent with the GET method, you can use $_GET
  $say = htmlspecialchars($_POST['say']);
  $to  = htmlspecialchars($_POST['to']);
  echo  $say, ' ', $to;
?>

					

This example displays a page with the data we sent. You can see this in action in our example php-example.html file — which contains the same example form as we saw before, with a 方法 of POST action of php-example.php . When it is submitted, it sends the form data to php-example.php , which contains the PHP code seen in the above block. When this code is executed, the output in the browser is Hi Mom .

注意: This example won't work when you load it into a browser locally — browsers cannot interpret PHP code, so when the form is submitted the browser will just offer to download the PHP file for you. To get it to work, you need to run the example through a PHP server of some kind. Good options for local PHP testing are MAMP (Mac and Windows) and AMPPS (Mac, Windows, Linux).

Note also that if you are using MAMP but don't have MAMP Pro installed (or if the MAMP Pro demo time trial has expired), you might have trouble getting it working. To get it working again, we have found that you can load up the MAMP app, then choose the menu options MAMP > 首选项 > PHP , and set "Standard Version:" to "7.2.x" (x will differ depending on what version you have installed).

Example: Python

This example shows how you would use Python to do the same thing — display the submitted data on a web page. This uses the Flask framework for rendering the templates, handling the form data submission, etc. (see python-example.py ).

from flask import Flask, render_template, request
app = Flask(__name__)
@app.route('/', methods=['GET', 'POST'])
def form():
    return render_template('form.html')
@app.route('/hello', methods=['GET', 'POST'])
def hello():
    return render_template('greeting.html', say=request.form['say'], to=request.form['to'])
if __name__ == "__main__":
    app.run()

					

The two templates referenced in the above code are as follows (these need to be in a subdirectory called templates in the same directory as the python-example.py file, if you try to run the example yourself):

  • form.html : The same form as we saw above in the The POST method section but with the action 设为 {{ url_for('hello') }} . This is a Jinja2 template, which is basically HTML but can contain calls to the Python code that is running the web server contained in curly braces. url_for('hello') is basically saying "redirect to /hello when the form is submitted".
  • greeting.html : This template just contains a line that renders the two bits of data passed to it when it is rendered. This is done via the hello() function seen above, which runs when the /hello URL is navigated to.

注意: Again, this code won't work if you just try to load it into a browser directly. Python works a bit differently to PHP — to run this code locally you'll need to install Python/PIP , then install Flask using pip3 install flask . At this point you should be able to run the example using python3 python-example.py , then navigating to localhost:5042 in your browser.

Other languages and frameworks

There are many other server-side technologies you can use for form handling, including Perl, Java, .Net, Ruby, etc. Just pick the one you like best. That said, it's worth noting that it's very uncommon to use these technologies directly because this can be tricky. It's more common to use one of the many high quality frameworks that make handling forms easier, such as:

It's worth noting that even using these frameworks, working with forms isn't necessarily easy . But it's much easier than trying to write all the functionality yourself from scratch, and will save you a lot of time.

注意: It is beyond the scope of this article to teach you any server-side languages or frameworks. The links above will give you some help, should you wish to learn them.

A special case: sending files

Sending files with HTML forms is a special case. Files are binary data — or considered as such — whereas all other data is text data. Because HTTP is a text protocol, there are special requirements for handling binary data.

The enctype attribute

This attribute lets you specify the value of the Content-Type HTTP header included in the request generated when the form is submitted. This header is very important because it tells the server what kind of data is being sent. By default, its value is application/x-www-form-urlencoded . In human terms, this means: "This is form data that has been encoded into URL parameters."

If you want to send files, you need to take three extra steps:

  • 设置 方法 属性到 POST because file content can't be put inside URL parameters.
  • Set the value of enctype to multipart/form-data because the data will be split into multiple parts, one for each file plus one for the text data included in the form body (if text is also entered into the form).
  • Include one or more <input type="file"> controls to allow your users to select the file(s) that will be uploaded.

例如:

<form method="post" action="https://www.foo.com" enctype="multipart/form-data">
  <div>
    <label for="file">Choose a file</label>
    <input type="file" id="file" name="myFile">
  </div>
  <div>
    <button>Send the file</button>
  </div>
</form>

					

注意: Servers can be configured with a size limit for files and HTTP requests in order to prevent abuse.

Security issues

Each time you send data to a server, you need to consider security. HTML forms are by far the most common server attack vectors (places where attacks can occur). The problems never come from the HTML forms themselves — they come from how the server handles data.

Website security article of our server-side learning topic discusses a number of common attacks and potential defenses against them in detail. You should go and check that article out, to get an idea of what's possible.

Be paranoid: Never trust your users

So, how do you fight these threats? This is a topic far beyond this guide, but there are a few rules to keep in mind. The most important rule is: never ever trust your users, including yourself; even a trusted user could have been hijacked.

All data that comes to your server must be checked and sanitized. Always. No exception.

  • Escape potentially dangerous characters . The specific characters you should be cautious with vary depending on the context in which the data is used and the server platform you employ, but all server-side languages have functions for this. Things to watch out for are character sequences that look like executable code (such as JavaScript or SQL commands).
  • Limit the incoming amount of data to allow only what's necessary .
  • Sandbox uploaded files . Store them on a different server and allow access to the file only through a different subdomain or even better through a completely different domain.

You should be able to avoid many/most problems if you follow these three rules, but it's always a good idea to get a security review performed by a competent third party. Don't assume that you've seen all the possible problems.

摘要

As we'd alluded to above, sending form data is easy, but securing an application can be tricky. Just remember that a front-end developer is not the one who should define the security model of the data. It's possible to perform client-side form validation , but the server can't trust this validation because it has no way to truly know what has really happened on the client-side.

If you've worked your way through these tutorials in order, you now know how to markup and style a form, do client-side validation, and have some idea about submitting a form.

另请参阅

If you want to learn more about securing a web application, you can dig into these resources:

In this module

高级话题

发现此页面有问题吗?

最后修改: , 由 MDN 贡献者

  1. Complete beginners start here!
  2. Web 快速入门
    1. Getting started with the Web overview
    2. 安装基本软件
    3. What will your website look like?
    4. 处理文件
    5. HTML 基础
    6. CSS 基础
    7. JavaScript 基础
    8. 发布您的网站
    9. How the Web works
  3. HTML — Structuring the Web
  4. HTML 介绍
    1. Introduction to HTML overview
    2. Getting started with HTML
    3. What's in the head? Metadata in HTML
    4. HTML text fundamentals
    5. Creating hyperlinks
    6. Advanced text formatting
    7. Document and website structure
    8. Debugging HTML
    9. Assessment: Marking up a letter
    10. Assessment: Structuring a page of content
  5. 多媒体和嵌入
    1. Multimedia and embedding overview
    2. Images in HTML
    3. Video and audio content
    4. From object to iframe — other embedding technologies
    5. Adding vector graphics to the Web
    6. Responsive images
    7. Assessment: Mozilla splash page
  6. HTML 表格
    1. HTML tables overview
    2. HTML table basics
    3. HTML Table advanced features and accessibility
    4. Assessment: Structuring planet data
  7. CSS — Styling the Web
  8. CSS 第一步
    1. CSS first steps overview
    2. What is CSS?
    3. Getting started with CSS
    4. How CSS is structured
    5. How CSS works
    6. Using your new knowledge
  9. CSS 构建块
    1. CSS building blocks overview
    2. Cascade and inheritance
    3. CSS 选择器
    4. The box model
    5. Backgrounds and borders
    6. Handling different text directions
    7. Overflowing content
    8. Values and units
    9. Sizing items in CSS
    10. Images, media, and form elements
    11. Styling tables
    12. Debugging CSS
    13. Organizing your CSS
  10. 样式化文本
    1. Styling text overview
    2. Fundamental text and font styling
    3. Styling lists
    4. Styling links
    5. Web fonts
    6. Assessment: Typesetting a community school homepage
  11. CSS 布局
    1. CSS layout overview
    2. Introduction to CSS layout
    3. Normal Flow
    4. Flexbox
    5. Grids
    6. Floats
    7. 位置
    8. Multiple-column Layout
    9. Responsive design
    10. Beginner's guide to media queries
    11. Legacy Layout Methods
    12. Supporting Older Browsers
    13. Fundamental Layout Comprehension
  12. JavaScript — Dynamic client-side scripting
  13. JavaScript 第一步
    1. JavaScript first steps overview
    2. What is JavaScript?
    3. A first splash into JavaScript
    4. What went wrong? Troubleshooting JavaScript
    5. Storing the information you need — Variables
    6. Basic math in JavaScript — Numbers and operators
    7. Handling text — Strings in JavaScript
    8. Useful string methods
    9. 数组
    10. Assessment: Silly story generator
  14. JavaScript 构建块
    1. JavaScript building blocks overview
    2. Making decisions in your code — Conditionals
    3. Looping code
    4. Functions — Reusable blocks of code
    5. Build your own function
    6. Function return values
    7. 事件介绍
    8. Assessment: Image gallery
  15. 引入 JavaScript 对象
    1. Introducing JavaScript objects overview
    2. Object basics
    3. 对象原型
    4. Object-oriented programming concepts
    5. Classes in JavaScript
    6. Working with JSON data
    7. Object building practice
    8. Assessment: Adding features to our bouncing balls demo
  16. 异步 JavaScript
    1. Asynchronous JavaScript overview
    2. General asynchronous programming concepts
    3. Introducing asynchronous JavaScript
    4. Cooperative asynchronous Java​Script: Timeouts and intervals
    5. Graceful asynchronous programming with Promises
    6. Making asynchronous programming easier with async and await
    7. Choosing the right approach
  17. 客户端侧 Web API
    1. 客户端侧 Web API
    2. Introduction to web APIs
    3. Manipulating documents
    4. Fetching data from the server
    5. Third party APIs
    6. Drawing graphics
    7. Video and audio APIs
    8. Client-side storage
  18. Web forms — Working with user data
  19. Core forms learning pathway
    1. Web forms overview
    2. Your first form
    3. How to structure a web form
    4. Basic native form controls
    5. The HTML5 input types
    6. Other form controls
    7. Styling web forms
    8. Advanced form styling
    9. UI pseudo-classes
    10. Client-side form validation
    11. Sending form data
  20. Advanced forms articles
    1. How to build custom form controls
    2. Sending forms through JavaScript
    3. CSS property compatibility table for form controls
  21. Accessibility — Make the web usable by everyone
  22. Accessibility guides
    1. Accessibility overview
    2. What is accessibility?
    3. HTML: A good basis for accessibility
    4. CSS and JavaScript accessibility best practices
    5. WAI-ARIA basics
    6. Accessible multimedia
    7. Mobile accessibility
  23. Accessibility assessment
    1. Assessment: Accessibility troubleshooting
  24. Tools and testing
  25. Client-side web development tools
    1. Client-side web development tools index
    2. Client-side tooling overview
    3. Command line crash course
    4. Package management basics
    5. Introducing a complete toolchain
    6. Deploying our app
  26. Introduction to client-side frameworks
    1. Client-side frameworks overview
    2. Framework main features
  27. React
    1. Getting started with React
    2. Beginning our React todo list
    3. Componentizing our React app
    4. React interactivity: Events and state
    5. React interactivity: Editing, filtering, conditional rendering
    6. Accessibility in React
    7. React resources
  28. Ember
    1. Getting started with Ember
    2. Ember app structure and componentization
    3. Ember interactivity: Events, classes and state
    4. Ember Interactivity: Footer functionality, conditional rendering
    5. Routing in Ember
    6. Ember resources and troubleshooting
  29. Vue
    1. Getting started with Vue
    2. Creating our first Vue component
    3. Rendering a list of Vue components
    4. Adding a new todo form: Vue events, methods, and models
    5. Styling Vue components with CSS
    6. Using Vue computed properties
    7. Vue conditional rendering: editing existing todos
    8. Focus management with Vue refs
    9. Vue resources
  30. Svelte
    1. Getting started with Svelte
    2. Starting our Svelte Todo list app
    3. Dynamic behavior in Svelte: working with variables and props
    4. Componentizing our Svelte app
    5. Advanced Svelte: Reactivity, lifecycle, accessibility
    6. Working with Svelte stores
    7. TypeScript support in Svelte
    8. Deployment and next steps
  31. Angular
    1. Getting started with Angular
    2. Beginning our Angular todo list app
    3. Styling our Angular app
    4. Creating an item component
    5. Filtering our to-do items
    6. Building Angular applications and further resources
  32. Git and GitHub
    1. Git and GitHub overview
    2. Hello World
    3. Git Handbook
    4. Forking Projects
    5. About pull requests
    6. Mastering Issues
  33. Cross browser testing
    1. Cross browser testing overview
    2. Introduction to cross browser testing
    3. Strategies for carrying out testing
    4. Handling common HTML and CSS problems
    5. Handling common JavaScript problems
    6. Handling common accessibility problems
    7. Implementing feature detection
    8. Introduction to automated testing
    9. Setting up your own test automation environment
  34. Server-side website programming
  35. 第一步
    1. First steps overview
    2. Introduction to the server-side
    3. Client-Server overview
    4. Server-side web frameworks
    5. Website security
  36. Django Web 框架 (Python)
    1. Django web framework (Python) overview
    2. 介绍
    3. 设置开发环境
    4. Tutorial: The Local Library website
    5. Tutorial Part 2: Creating a skeleton website
    6. Tutorial Part 3: Using models
    7. Tutorial Part 4: Django admin site
    8. Tutorial Part 5: Creating our home page
    9. Tutorial Part 6: Generic list and detail views
    10. Tutorial Part 7: Sessions framework
    11. Tutorial Part 8: User authentication and permissions
    12. Tutorial Part 9: Working with forms
    13. Tutorial Part 10: Testing a Django web application
    14. Tutorial Part 11: Deploying Django to production
    15. Web application security
    16. Assessment: DIY mini blog
  37. Express Web Framework (node.js/JavaScript)
    1. Express Web Framework (Node.js/JavaScript) overview
    2. Express/Node introduction
    3. Setting up a Node (Express) development environment
    4. Express tutorial: The Local Library website
    5. Express Tutorial Part 2: Creating a skeleton website
    6. Express Tutorial Part 3: Using a database (with Mongoose)
    7. Express Tutorial Part 4: Routes and controllers
    8. Express Tutorial Part 5: Displaying library data
    9. Express Tutorial Part 6: Working with forms
    10. Express Tutorial Part 7: Deploying to production
  38. Further resources
  39. Common questions
    1. HTML questions
    2. CSS questions
    3. JavaScript questions
    4. Web mechanics
    5. Tools and setup
    6. Design and accessibility