From 7662afc17b58894567b448f2485625a927bd7223 Mon Sep 17 00:00:00 2001 From: Javier Velilla Date: Fri, 10 Feb 2017 18:02:17 -0300 Subject: [PATCH 1/9] Fixed typos Updated document, fixed typos. --- doc/workbook/basics/basics.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/workbook/basics/basics.md b/doc/workbook/basics/basics.md index ce04f31e..6dbfc1ed 100644 --- a/doc/workbook/basics/basics.md +++ b/doc/workbook/basics/basics.md @@ -15,7 +15,7 @@ Nav: [Workbook](../workbook.md) :: [Handling Requests: Form/Query Parameter](../ ## EWF service structure -The following code describes the basic structure of an EWF basic service that handles HTTP requests. We will need to define a Service Launcher and a Request Execution implementation. +The following code describes the basic structure of an EWF basic service that handles HTTP requests. We will need to define a `Service Launcher` and a `Request Execution` implementation. ```eiffel class @@ -90,7 +90,7 @@ The **WSF_REQUEST** gives access to the incoming data; the class provides featur The **WSF_RESPONSE** provides features to define the response with information such as HTTP status codes (10x,20x, 30x, 40x, and 50x), response headers (Content-Type, Content-Length, etc.) and obviously the body of the message itself. -**APPLICATION** is the root class of our example, it launches the application, using the corresponding connector, Which connector? this depends how you want to run it cgi, fcgi,standalone. For development is recommended to use a standalone web server written in Eiffel, and run the execution within the EiffelStudio debugger. For production fcgi (or cgi) using Apache or another popular web server. +**APPLICATION** is the root class of our example, it launches the application, using the corresponding connector, Which connector? this depends how do you want to run it `cgi`, `fcgi`, `standalone`. For development is recommended to use a standalone web server written in Eiffel, and run the execution within the EiffelStudio debugger. For production fcgi (or cgi) using Apache or another popular web server. ![Launcher Hierarchy](./Launcher Hierarchy.png "Launcher Hierarchy") @@ -107,7 +107,7 @@ A basic EWF service inherits from **WSF_DEFAULT_SERVICE**, which has a formal g The **APPLICATION_EXECUTION** class inherits from **WSF_EXECUTION** interface, which is instantiated for each incoming request. **WSF_EXECUTION** inherit from **WGI_EXECUTION** which is the low level entry point in EWF, handling each incoming request with a single procedure ```execute (req: WSF_REQUEST; res: WSF_RESPONSE) ...```. -In the **APPLICATION_EXECUTION** class class you will need to implement implement the **execute** feature, get data from the request *req* and write the response in *res*. +In the **APPLICATION_EXECUTION** class class you will need to implement the **execute** feature, get data from the request *req* and write the response in *res*. ![Execution Hierarchy](./APPLICATION_EXECUTION.png "Application Execution ") From 828c75f0c23d4fee77d7d0c3340a0cdba293952e Mon Sep 17 00:00:00 2001 From: Javier Velilla Date: Fri, 10 Feb 2017 18:04:39 -0300 Subject: [PATCH 2/9] Cosmetic --- doc/workbook/basics/basics.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/workbook/basics/basics.md b/doc/workbook/basics/basics.md index 6dbfc1ed..2fc0e40f 100644 --- a/doc/workbook/basics/basics.md +++ b/doc/workbook/basics/basics.md @@ -60,7 +60,7 @@ end ``` When using the "standalone" connector (or the deprecated "nino" connector), by default the service listens on port 80, but often this port is already used by other applications, so it is recommended to use another port. -To define another port, redefine the feature `initialize' and set up a new port number using the service options (see below). +To define another port, redefine the feature `initialize` and set up a new port number using the service options (see below). ```eiffel @@ -103,7 +103,7 @@ Other connectors: **WSF_CGI_SERVICE_LAUNCHER** **WSF_LIBFCGI_SERVICE_LAUNCHER** -A basic EWF service inherits from **WSF_DEFAULT_SERVICE**, which has a formal generic that should conform to **WSF_EXECUTION** class with a `make' creation procedure, in our case the class **APPLICATION_EXECUTION**. +A basic EWF service inherits from **WSF_DEFAULT_SERVICE**, which has a formal generic that should conform to **WSF_EXECUTION** class with a `make` creation procedure, in our case the class **APPLICATION_EXECUTION**. The **APPLICATION_EXECUTION** class inherits from **WSF_EXECUTION** interface, which is instantiated for each incoming request. **WSF_EXECUTION** inherit from **WGI_EXECUTION** which is the low level entry point in EWF, handling each incoming request with a single procedure ```execute (req: WSF_REQUEST; res: WSF_RESPONSE) ...```. From 659695972438bae014eae2d5319aa5ab226fc6ab Mon Sep 17 00:00:00 2001 From: Javier Velilla Date: Fri, 10 Feb 2017 18:32:48 -0300 Subject: [PATCH 3/9] Cosmetic --- doc/workbook/handling_request/form.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/workbook/handling_request/form.md b/doc/workbook/handling_request/form.md index f5f7f339..1d15e5b8 100644 --- a/doc/workbook/handling_request/form.md +++ b/doc/workbook/handling_request/form.md @@ -17,17 +17,17 @@ Nav: [Workbook](../workbook.md) :: [Basic Concepts](../basics/basics.md) :: [Han - [Examples](#examples) -An HTML Form can handle GET and POST requests. -When we use a form with method GET, the data is attached at the end of the url for example: +An HTML Form can handle `GET` and `POST` requests. +When we use a form with method `GET`, the data is attached at the end of the url for example: >http://wwww.example.com?key1=value1&...keyn=valuen -If we use the method POST, the data is sent to the server in a different line. +If we use the method `POST`, the data is sent to the server in a different line. Extracting form data from the server side is one of the most tedious parts. If you do it by hand, you will need to parse the input, you'll have to URL-decode the value. -Here we will show you how to read input submitted by a user using a Form (GET and POST). +Here we will show you how to read input submitted by a user using a Form (`GET` and `POST`). * How to handle missing values: * client side validattion, server side validations, set default if it's a valid option. * How to populate Eiffel objects from the request data. From b456f02a14fa383c66bc18e6c48a20755083208a Mon Sep 17 00:00:00 2001 From: Javier Velilla Date: Fri, 10 Feb 2017 18:55:38 -0300 Subject: [PATCH 4/9] Updated documentation Cosmetic, style, typos. --- doc/workbook/handling_request/form.md | 34 +++++++++++++-------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/doc/workbook/handling_request/form.md b/doc/workbook/handling_request/form.md index 1d15e5b8..c19bec47 100644 --- a/doc/workbook/handling_request/form.md +++ b/doc/workbook/handling_request/form.md @@ -56,29 +56,29 @@ EWF [WSF_REQUEST]() class, provides features to handling this form parsing autom WSF_REQUEST.form_parameter (a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE -- Field for name `a_name'. -The values supplied to form_parameter and query_parameter are case sensitive. +The values supplied to `form_parameter` and `query_parameter` are _case_ _sensitive_. ### Read Data -The previous features, let you read the data one way for GET request and a different way for POST request. WSF_REQUEST provide a feature to read all the data in a uniform way. +The previous features, let you read the data one way for `GET` request and a different way for `POST` request. **WSF_REQUEST** provide a feature to read all the data in a uniform way. WSF_REQUEST.item (a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE -- Variable named `a_name' from any of the variables container -- and following a specific order: form_, query_ and path_ parameters -So, you use **WSF_REQUEST.item** feature exactly the same way for GET and POST request. +So, you can use **WSF_REQUEST.item** feature exactly the same way for `GET` and `POST` request. ->Note: if a query parameter has the same name as a form paramenter req.item will retrieve the form paramenter. Remember the precedence: form > query > path +>Note: if a query parameter has the same name as a form paramenter req.item will retrieve the form paramenter. Remember the precedence: `form` > `query` > `path` ## Reading Parameters and Values -Suppose we have the following HTML5 form using Method POST. This HTML5 form has client side form validation using the new HTML5 attribute, you can do the same using Javascript. So in this case if the user does not fill the fields as expected the form will not be submitted to the server. +Suppose we have the following HTML5 form using method `POST`. This HTML5 form has client side form validation using the new HTML5 `attribute`, you can do the same using Javascript. So in this case if the user does not fill the fields as expected the form will not be submitted to the server. ->Note: You want to validate on the server side because you can protect against the malicious user, who can easily bypass your JavaScript and submit dangerous input to the server. +>Note: it is recommended to validate client side input on the server side (as a double check) because you can protect against the malicious user, who can easily bypass your JavaScript and submit dangerous input to the server. ```

EWF Handling Client Request: Form example

@@ -117,7 +117,7 @@ Suppose we have the following HTML5 form using Method POST. This HTML5 form has ### How to read all parameter names -To read all the parameters names we simple call WSF_REQUEST.form_parameters. +To read all the parameters names we simple call **WSF_REQUEST.form_parameters**. ``` req: WSF_REQUEST @@ -126,7 +126,7 @@ To read all the parameters names we simple call WSF_REQUEST.form_parameters. ### How to read single values -To read a particular parameter, a single value, for example `given-name', we simple call WSF_REQUEST.form_parameter (a_name) and we check if it's attached to WSF_STRING (represents a String parameter) +To read a particular parameter, a single value, for example `given-name`, we simple call **WSF_REQUEST.form_parameter (a_name)** and we check if it's attached to **WSF_STRING** (represents a String parameter) ``` req: WSF_REQUEST if attached {WSF_STRING} req.form_paramenter ('given-name') as l_given_name then @@ -140,7 +140,7 @@ To read a particular parameter, a single value, for example `given-name', we sim ### How to read multiple values -To read multiple values, for example in the case of `languages', we simple call WSF_REQUEST.form_parameter (a_name) and we check if it's attached to WSF_MULTIPLE_STRING (represents a String parameter) +To read multiple values, for example in the case of `languages`, we simple call **WSF_REQUEST.form_parameter (a_name)** and we check if it's attached to **WSF_MULTIPLE_STRING** (represents a String parameter) ``` req: WSF_REQUEST @@ -159,16 +159,16 @@ To read multiple values, for example in the case of `languages', we simple call -- Value missing end ``` -In this case we are handling strings values, but in some cases you will need to do a conversion, betweend the strings that came from the request to map them to your domain model. +In this case we are handling strings values, but in some cases you will need to do a conversion, between the strings that came from the request to map them to your domain model. ### How to read table values This is particularly useful when you have a request with the following format -``` ``` +`````` -To read table values, for example in the case of `tab', we simple call WSF_REQUEST.form_parameter (a_name) and we check if it's attached to WSF_TABLE. +To read table values, for example in the case of `tab`, we simple call **WSF_REQUEST.form_parameter (a_name)** and we check if it's attached to **WSF_TABLE**. ``` if attached {WSF_TABLE} req.query_parameter ("tab") as l_tab then @@ -193,14 +193,14 @@ end ## Reading Raw Data -You can also access the data in raw format, it means you will need to parse and url-decode it, and also you will not be able to use the previous features, by default, to enable that you need to call `req.set_raw_input_data_recorded (True)'. This feature (reading raw data) is useful if you are reading POST data with JSON or XML formats, but it's not convinient for HTML forms. +You can also access the data in raw format, it means you will need to parse and url-decode it, and also you will not be able to use the previous features, by default, to enable that, you will need to call `req.set_raw_input_data_recorded (True)`. This feature (reading raw data) is useful if you are reading `POST` data with JSON or XML formats, but it's not convinient for HTML forms. To read raw data you need to do this ``` l_raw_data:STRING - req.set_raw_input_data_recorded (True) -- + req.set_raw_input_data_recorded (True) create l_raw_data.make_empty req.read_input_data_into (l_raw_data) ``` @@ -211,7 +211,7 @@ To read raw data you need to do this ## Upload Files How can we read data when the date come from an uploaded file/s?. -HTML supports a form element ``` ``` to upload a single file and ``` ``` to upload multiple files. +HTML supports a form element `````` to upload a single file and ``` ``` to upload multiple files. So supose we have the following form @@ -240,14 +240,14 @@ So supose we have the following form ``` -The class WSF_REQUEST has defines mechanism to work with uploaded files. We can call the query +The class **WSF_REQUEST** has a mechanism to work with uploaded files. We can call the query ``` WSF_REQUEST.has_uploaded_file: BOOLEAN -- Has any uploaded file? ``` -to check if the request form parameters has any uploaded file, and we can call the feature +to check if the request form parameters has any uploaded file, we can call the feature ``` WSF_REQUEST.uploaded_files: ITERABLE [WSF_UPLOADED_FILE] From 91a5fb28863bdd9b7497b32e4f446447ce0271f5 Mon Sep 17 00:00:00 2001 From: Javier Velilla Date: Fri, 10 Feb 2017 19:37:35 -0300 Subject: [PATCH 5/9] Cosmetic --- doc/workbook/handling_request/form.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/workbook/handling_request/form.md b/doc/workbook/handling_request/form.md index c19bec47..8c07d049 100644 --- a/doc/workbook/handling_request/form.md +++ b/doc/workbook/handling_request/form.md @@ -259,9 +259,9 @@ WSF_REQUEST.uploaded_files: ITERABLE [WSF_UPLOADED_FILE] --| error: if /= 0 , there was an error : TODO ... --| size: size of the file given by the http request ``` -to iterate over the uploaded files if any, and the details in the class [WSF_UPLOADED_FILE]. +to iterate over the uploaded files if any, and the details in the class **WSF_UPLOADED_FILE**. -The following snipet code show how to work with Uploaded files using EWF [WSF_REQUEST] class, in the example +The following snipet code show how to work with Uploaded files using EWF **WSF_REQUEST** class, in the example we build a simple html answer with basic information, if there is not uploaded files, we send a 400 status code and a simple message. From 65e1b1bfed11a8fb8c9e7e9b79fbe71d33c4c5df Mon Sep 17 00:00:00 2001 From: Javier Velilla Date: Fri, 10 Feb 2017 19:55:18 -0300 Subject: [PATCH 6/9] Cosmetic --- doc/workbook/handling_request/headers.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/doc/workbook/handling_request/headers.md b/doc/workbook/handling_request/headers.md index 5f0945f0..76bc72d2 100644 --- a/doc/workbook/handling_request/headers.md +++ b/doc/workbook/handling_request/headers.md @@ -84,7 +84,7 @@ GET http://eiffel.org/search?q=EiffelBase HTTP/1.1 Overview of the features * HTTP method - - The function `request_method: READABLE_STRING_8` gives access to the HTTP request method, (usually GET or POST in conventional Web Applications), but with the raise of REST APIs other methods are also frequently used such as HEAD, PUT, DELETE, OPTIONS, or TRACE. + - The function `request_method: READABLE_STRING_8` gives access to the HTTP request method, (usually `GET` or `POST` in conventional Web Applications), but with the raise of REST APIs other methods are also frequently used such as `HEAD`, `PUT`, `DELETE`, `OPTIONS`, or `TRACE`. A few functions helps determining quickly the nature of the request method: - `is_get_request_method: BOOLEAN -- Is Current a GET request method?` - `is_put_request_method: BOOLEAN -- Is Current a PUT request method?` @@ -302,11 +302,10 @@ To be completed. #### Detecting Browser Types -The User-Agent header identifies the specific browser/client that is sending the request. The following code shows a [EWF service](./headers/browser_name/application.e) that sends browser-specific responses. +The User-Agent header identifies the specific browser/client that is sending the request. The following code shows an [EWF service](./headers/browser_name/application.e) that sends browser-specific responses. The examples uses the ideas based on the [Browser detection using the user agent](https://developer.mozilla.org/en-US/docs/Browser_detection_using_the_user_agent) article. -Basically the code check if the header user_agent exist and then call the ```browser_name (a_user_agent: READABLE_STRING_8): READABLE_STRING_32``` -feature to retrieve the current browser name or Unknown in other case. +Basically the code check if the header `user_agent` exist and then call the ```browser_name (a_user_agent: READABLE_STRING_8): READABLE_STRING_32``` feature to retrieve the current browser name or Unknown in other case. ```eiffel class From c6de55b903162e6afa264a81fa9302b37e729863 Mon Sep 17 00:00:00 2001 From: Javier Velilla Date: Fri, 10 Feb 2017 20:31:08 -0300 Subject: [PATCH 7/9] Cosmetic --- doc/workbook/generating_response/generating_response.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/workbook/generating_response/generating_response.md b/doc/workbook/generating_response/generating_response.md index 977daf77..482066df 100644 --- a/doc/workbook/generating_response/generating_response.md +++ b/doc/workbook/generating_response/generating_response.md @@ -482,6 +482,7 @@ end ``` Using cURL to test the application +--- In the first call we use the ```res.redirect_now (l_engine_url)``` feature ``` From 5f1bb64d26cdd04fdf8003934ee67ad438187580 Mon Sep 17 00:00:00 2001 From: Javier Velilla Date: Fri, 10 Feb 2017 20:32:49 -0300 Subject: [PATCH 8/9] Update generating_response.md --- doc/workbook/generating_response/generating_response.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/workbook/generating_response/generating_response.md b/doc/workbook/generating_response/generating_response.md index 482066df..79dace72 100644 --- a/doc/workbook/generating_response/generating_response.md +++ b/doc/workbook/generating_response/generating_response.md @@ -698,7 +698,7 @@ take a look at constants classes such as [HTTP_MIME_TYPES](),[HTTP_HEADER_NAMES] res.put_string (l_msg) end ``` -The class [HTTP_HEADER]() also supplies a number of convenience routines for specifying common headers, in fact the features are inherited from the class [HTTP_HEADER_MODIFIER]. +The class [HTTP_HEADER]() also supplies a number of convenience routines for specifying common headers, in fact the features are inherited from the class [HTTP_HEADER_MODIFIER](). ```eiffel From 14e260bea4e3b814c5bfeb32dc7dbe4aa53d9d78 Mon Sep 17 00:00:00 2001 From: Javier Velilla Date: Fri, 10 Feb 2017 20:37:01 -0300 Subject: [PATCH 9/9] Cosmetic --- doc/workbook/handling_cookies/handling_cookies.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/workbook/handling_cookies/handling_cookies.md b/doc/workbook/handling_cookies/handling_cookies.md index 316ba48a..75b62eba 100644 --- a/doc/workbook/handling_cookies/handling_cookies.md +++ b/doc/workbook/handling_cookies/handling_cookies.md @@ -49,8 +49,8 @@ Client send cookies to server ## Write and Read Cookies. -To send a cookie to the client we should use the [HTTP_HEADER] class, and call ```h.put_cookie``` feature or -```h.put_cookie_with_expiration_date``` feature, see [How to set Cookies]() to learn the details, and the set it to response object [WSF_RESPONSE] as we saw previously. +To send a cookie to the client we should use the **HTTP_HEADER** class, and call ```h.put_cookie``` feature or +```h.put_cookie_with_expiration_date``` feature, see [How to set Cookies]() to learn the details, and the set it to response object **WSF_RESPONSE** as we saw previously. We will show an example.