Hypertext Transfer Protocol (HTTP)


HTTP

It is the protocol used in each World Wide Web transaction. The protocol is based on a Request/Answer architecture. Web browsers, Web servers and other Internet applications use HTTP to communicate. The client is typically a Web Browser and is known as: user agent. The client sends an HTTP Request and the server answers with an HTTP Response. Both, the HTTP Resquest and the HTTP Response have four parts:
  1. The status line
  2. The header
  3. A blank line
  4. The body
The figure below shows how a program called MyWebApplication request the item_price.html document using HTTP. The HTTP request has three parts: Header, a blank line and Data. The server HTTP response is also shown in this figure. The Content-Length element in the header indicates that the Data (in this case html) has a length of 221 bytes.
Es el protocolo usado en cada transacción del World Wide Web. El protocolo está basado en una arquitectura Solicitud/Respuesta. Exploradores Web, Servidores Web y otras aplicaciones para la Internet usan HTTP para comunicarse. El cliente es típicamente un Explorador de la Web y es conocido como: user agent. El cliente envía una HTTP Request y el servidor contesta con una HTTP Response. Ambas, la HTTP Request y la HTTP Response tienen cuatro partes:
  1. La línea de estado
  2. El encabezado
  3. Una línea vacía
  4. El cuerpo
La figura de abajo muestra como un programa llamado MyWebApplication solicita el documento item_price.html usando HTTP. La solicitud de HTTP tiene tres partes: Encabezado, una línea vacía y los datos. La respuesta del servidor en HTTP también se muestra en la figura. Elemento Content-Length del encabezado indica que los datos (en este caso html) tiene una longitud de 221 btyes.

HttpStructure

HTTP Request

A client begins a transaction by sending an HTTP Request to the server. The client may send several types of requests such as:
  • GET It is used to request a resource from the server (a file, a image, etc.)
  • POST It is used to send information to the server (this information may include data collected using a web page
  • PUT It is used to upload a resource (files: pdf, docx, jpg, etc.) to the server
  • HEAD It is similar to GET but the server sends only the status line and the header.
  • DELETE It deletes a resource that is located in the server.
  • CONNECT It establishes a tunnel to the server.
  • OPTIONS It describes the communications options.
  • TRACE It performs a message loop-back test.

Es el protocolo usado en cada transacción del World Wide Web. El protocolo está basado en una arquitectura Solicitud/Respuesta. Exploradores Web, Servidores Web y otras aplicaciones para la Internet usan HTTP para comunicarse. El cliente es típicamente un Explorador de la Web y es conocido como: user agent. El cliente puede enviar distintos tipos de solicitudes tales como:
  • GET es usado para solicitar un recurso desde el servidor (un archivo, una imagen, etc.)
  • POST es usado para enviar información al servidor (esta información puede incluir datos colectado por una página web.)
  • PUT es usado para subir un recurso al servidor (archivos: pdf, docx, jpg, etc.)
  • HEAD es semejante a GET pero el servidor solo envía la línea de estado y el encabezado.
  • DELETE borra un recurso que está en el servidor.
  • CONNECT establece un túnel hacia el servidor.
  • OPTIONS describe la opciones de comunicación.
  • TRACE realiza una prueba de ida y regreso de un mensaje.

HTTP codes (for Responses)

HTTP is based on codes that indicate the result of the client request. The most common values are: 200 are 400. The figure below how these codes works. In the first figure, a web browser connects to a web server such as www.yahoo.com and sends an HTTP request. The respective web server returns 200 OK and the HTML corresponding to the document requested. In the second figure, the client sends an incorrect request; the web server responds with 400 Bad request. To simplify the use of HTTP, Wintempla provides the classes: Web::Http, Web::HttpRequest and Web::HttpResponse.
El HTTP está basado en códigos que indican el resultado de la solicitud del cliente. Los valores más comunes son: 200 y 400. La figura de abajo muestra cómo funcionan estos códigos. In la primera figura, un explorador web se conectar a un servidor web tal como www.yahoo.com y envía una solicitud de HTTP. El servidor web respectivo regresa 200 OK y el código de HTML respectivo. En la segunda figura, el cliente envía una solicitud inválida; el servidor web contesta con 400 Bad request. Para simplificar el uso de HTTP, Wintempla proporciona las clases: Web::Http, Web::HttpRequest y Web::HttpResponse.

http

Tip
The figure below shows how Google Chrome requests information about an item using a Web page that has input elements (two textboxes and a button). In this case, the Data of the request includes the information that the user provided in the Web page. The Web server creates HTML as illustrated and returns the information using HTTP.
La figura de abajo muestra como Google Chrome solicita información acercar de un producto usando una página web que tiene elementos de entrada (dos cajas de texto y un botón). En este caso, los datos de la solicitud incluyen la información que el usuario proporcionó en la página Web. El servidor Web crea HTML como se ilustra y regresa la información usando HTTP.

HttpStructureDll

Problem 1
Search over the Internet to get a list of HTTP codes.
Busque en la Internet por la lista de códigos HTTP.

Sys::Socket

Wintempla encapsulates Winsock in the Sys::Socket class. Basically there are three commands to operate Winsock: connect, send, and recv. The equivalent commands in the Sys::Socket class are: Connect, Send, Receive and Disconnect. You may use the Winsock commands directly or use the Sys::Socket class.
Wintempla encapsula Winsock en la clase Sys::Socket. Básicamente hay tres comandos para usar Winsock: connect, send y recv. Los comandos equivalentes en la clase Sys::Socket son: Connect, Send, Receive y Disconnect. Usted puede usar los comandos de Winsock directamente o usar la clase Sys::Socket.

Tip
Most programming languages and most computer operating systems support sockets including mobile devices.
La mayoría de los lenguajes de programación y la mayoría de los sistemas operativos de computadoras (incluyendo los dispositivos móviles) soportan los sockets.

GET

In order to send a GET in HTTP the word GET followed of one space, one regular diagonal (for the default document), another space, the word HTTP, one regular diagonal, the number 1.0, and two line returns. The figure shows the main components of an HTTP request: the method, the resource, the major version, and the minor version.
A fin de enviar un GET en HTTP se usa la palabra GET seguida de un espacio, una diagonal normal (para el documento de defecto), otro espacio, la palabra HTTP, una diagonal normal, el número 1.0 y dos retornos de carro. La figura muestra los componentes principales de una solicitud de HTTP: el método, el recurso, la versión mayor y la versión menor.

Get

Problem 2
Create a dialog application called WebBrowser using Wintempla to execute an HTTP transaction. Once the application has been created, add a textbox as shown with the multiline property and vertical and horizontal scrollbars as shown. Add also a button to connect. Do not forget to edit the stdafx.h file to enable the sockets in your program.
Cree una aplicación de diálogo llamada WebBrowser usando Wintempla para realizar una transacción de HTTP. Una vez creada la aplicación agregue una caja de texto con la propiedad de multi-línea y con barras de desplazamiento horizontal y vertical como se muestra. Agregue también un botón para conectarse. No se olvide de editar el archivo stdafx.h para habilitar los sockets en su programa.

stdafx.h
. . .
//_________________________________________ OpenGL
//#define WIN_OPENGL_SUPPORT
//_________________________________________ Sockets & Cryptography
#define WIN_SOCKETS_SUPPORT
//_________________________________________ DirectX
//#define WIN_DIRECTX
//
. . .


WebBrowserRun

WebBrowser.cpp
. . .
void WebBrowser::btConnect_Click(Win::Event& e)
{
     Win::BusyCursor busyCursor(true);
     //____________________________________________________________ 1. Connect
     Sys::Socket socket;
     if (socket.Connect(L"www.ugto.mx", 80) == SOCKET_ERROR)
     {
          this->MessageBoxW(socket.GetLastErrorDesc(), L"WebBrowser", MB_OK | MB_ICONERROR);     
          return;
     }     
     //____________________________________________________________ 2. Send HTTP Request
     Web::HttpRequest httpRequest;
     httpRequest.method = L"GET";
     httpRequest.resource = L"/";
     //request.resource = L"/ex.htm";
     httpRequest.head[L"Connection"] = L"close";
     httpRequest.head[L"Accept"] = L"text/html";
     int result = socket.Send(httpRequest);
     if (result == SOCKET_ERROR)
     {
          this->MessageBox(socket.GetLastErrorDesc(), L"WebBrowser", MB_OK | MB_ICONERROR);
          return;
     }
     else if (result == SOCKET_DISCONNECTED)
     {
          this->MessageBox(L"Connection lost", L"WebBrowser", MB_OK | MB_ICONERROR);
          return;
     }
     socket.ShutdownSend();
     //___________________________________________________________ 3. Receive HTTP Response
     Web::HttpResponse httpResponse;
     result = socket.Receive(httpResponse);
     if (result == SOCKET_ERROR)
     {
          this->MessageBox(socket.GetLastErrorDesc(), L"WebBrowser", MB_OK | MB_ICONERROR);
          return;
     }
     else if (result == SOCKET_DISCONNECTED)
     {
          this->MessageBox(L"Connection lost", L"WebBrowser", MB_OK | MB_ICONERROR);
          return;
     }
     wstring text;
     httpResponse.GetHeadText(text);
     tbxOutput.Text = text;
     //
     httpResponse.GetBodyText(text);
     tbxOutput.Text += text;
}


Problem 3
Repeat the previous problem using Win32 (Desktop Windows Application).
Repita el problema previo usando Win32 (Aplicación de Escritorio de Windows).

WebBrowser32Run

WebBrowser32.cpp
//_________________________________________________ WebBrowser32.cpp
#include "stdafx.h"
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include "WebBrowser32.h"
#include <winsock2.h> // Sockets
#pragma comment(lib, "ws2_32.lib")
//#include <mstcpip.h>
//#include <Ws2tcpip.h>
//#pragma comment(lib, "Ws2_32.lib")
#include <string>
using namespace std;
#define BUFFER_SIZE 64

INT_PTR Window_Open(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
     ::SetWindowText(hWnd, L"WebBrowser32");
     return TRUE;
}

INT_PTR btConnect_Click(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
     //_____________________________________________ Load Winsock 2.1
     WSADATA wsadata;
     ::WSAStartup(MAKEWORD(2, 1), &wsadata);
     //_____________________________________________ Get Host Address
     //ADDRINFOW *addinfo = NULL;
     //GetAddrInfoW(L"www.google.com", L"http", NULL, &addinfo);
     LPHOSTENT lpHostEntry = gethostbyname("www.google.com");
     if (lpHostEntry == NULL)
     {
          ::MessageBox(hWnd, L"gethostbyname", L"Error", MB_OK | MB_ICONERROR);
     }
     SOCKADDR_IN sa;
     sa.sin_family = AF_INET;
     sa.sin_port = htons(80);
     sa.sin_addr = *((LPIN_ADDR)*lpHostEntry->h_addr_list);
     //_____________________________________________ Create Socket
     SOCKET hsocket = INVALID_SOCKET;
     hsocket = (SOCKET)socket(AF_INET, SOCK_STREAM, 0);
     if (hsocket == INVALID_SOCKET)
     {
          ::MessageBox(hWnd, L"Create Socket", L"Error", MB_OK | MB_ICONERROR);
     }
     //_____________________________________________ Connect Socket
     if (connect(hsocket, (PSOCKADDR)&sa, sizeof(SOCKADDR_IN)) == SOCKET_ERROR)
     {
          ::MessageBox(hWnd, L"connect", L"Error", MB_OK | MB_ICONERROR);
     }
     //______________________________________________ Send Request
     char buffer[BUFFER_SIZE];
     _snprintf_s(buffer, BUFFER_SIZE, _TRUNCATE, "GET / HTTP/1.0\r\nConnection: close\r\n\r\n");
     if (send(hsocket, buffer, strlen(buffer), 0) == SOCKET_ERROR)
     {
          ::MessageBox(hWnd, L"send request", L"Error", MB_OK | MB_ICONERROR);
     }
     //___________________________________________________________ Receive HTTP Response
     string result;
     int receivedBytes = BUFFER_SIZE;
     while (receivedBytes != 0)
     {
          receivedBytes = recv(hsocket, buffer, BUFFER_SIZE, 0);
          if (receivedBytes == SOCKET_ERROR)
          {
               ::MessageBox(hWnd, L"recv HTTP response", L"Error", MB_OK | MB_ICONERROR);
               return 0;
          }
          result.append(buffer, receivedBytes);
     }
     //__________________________________________________________ Convert from UTF8 to wchar_t
     wstring wresult;
     size_t lengthUTF8 = result.length();
     if (lengthUTF8 > 0)
     {
          ++lengthUTF8;
          int cbUTF8 = static_cast<int>(lengthUTF8);
          int cchUTF16 = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, result.c_str(), cbUTF8, NULL, 0);
          if (cchUTF16 == 0) wresult.clear();
          wresult.resize(cchUTF16);
          int len = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, result.c_str(), cbUTF8, (wchar_t*)wresult.c_str(), cchUTF16);
          wresult.resize(cchUTF16 - 1);
          if (len == 0) wresult.clear();
     }
     //_______________________________________________________ Display Result
     ::SetWindowText(::GetDlgItem(hWnd, ID_TBX_OUTPUT), wresult.c_str());
     //_____________________________________________ Socket Clean Up
     if (hsocket != INVALID_SOCKET)
     {
          ::shutdown(hsocket, SD_BOTH);
          closesocket(hsocket);
     }
     //_____________________________________________ Unload Winsock
     ::WSACleanup();
     return TRUE;
}

INT_PTR CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
     switch (message)
     {
     case WM_INITDIALOG:
          return Window_Open(hWnd, wParam, lParam);
     case WM_COMMAND:
          if (LOWORD(wParam) == ID_BT_CONNECT) return btConnect_Click(hWnd, wParam, lParam);
          if (LOWORD(wParam) == IDCANCEL) ::EndDialog(hWnd, 0);
          break;
     }
     return (INT_PTR)FALSE;
}

int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE, LPTSTR cmdLine, int cmdShow)
{
     ::DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, WndProc);
     return 0;
}


Tip
When calling a receive data function such as recv or socket.recv, the function will
  • Return SOCKET_ERROR (-1), if there is an error.
  • Return zero, if the connection has been closed on the other end.
  • Return the number of bytes that were received.
  • Block program execution (or the respective thread) until data is available, see figure below. Be careful of this situation; you should call a receive function only when there are data ready to be received.
Call recv only when you know that there is something to receive.
Cuando se llama una función para recibir datos tal como recv or socket.Receive, la función:
  • Regresará SOCKET_ERROR (-1), si hay un error.
  • Regresará cero, si la conexión ha sido cerrado en el otro lado.
  • Regresará el número de bytes que fueron recibidos.
  • Bloqueará la ejecución del programa (o la thread respectiva) hasta que datos estén disponibles, ver figura mostrada debajo. Tenga cuidado de esta situación; llame una función para recibir datos solamente cuando existan datos listos para recibirse.
Llame recv solamente cuando usted sabe que hay algo por recibir.

socketReceive

MSG_WAITALL

When a socket uses the flag MSG_WAITALL when receiving data, the function will return until the buffer is filled. If there is not enough data to receive, the function will block the program execution until there is enough data to fill the buffer.
Cuando un socket usa la bandera MSG_WAITALL cuando recibe datos, la función regresará hasta que el buffer se llene. Por lo tanto, si no hay suficientes datos por recibir, la función bloqueará la ejecución del programa hasta que existan suficientes datos para llenar el buffer.

Multiple Sends

The figure below illustrates a common mistake made by beginner with sockets. If the program in one end of the socket executes one or more Sends to send a specific number of bytes, the program in the other end must call Receive (one or several times) until all data has been received. In the HTTP protocol, the Content-length header indicates how many bytes must be received. Note that data left in the socket will be removed in future calls to Receive producing unexpected results.
La figura de abajo ilustra un error común hecho por los inexpertos con los sockets. Si el programa en un extremo del socket ejecuta uno o más Sends para enviar un número específico de bytes, el programa en el otro lado debe llamar Receive (una o más veces) hasta que todos los datos han sido recibidos. En el protocolo de HTTP, el encabezado Content-length indica el número de bytes que deben ser recibidos. Note que datos que se quedan en el socket serán removidos en llamadas futuras a Receive produciendo resultados inesperados.

multipleSend

Receiving an HTTP Response or an HTTP Request

To receive an HTTP Response or an HTTP Request you must:
  1. Receive the Header by receiving data until you find an empty line
  2. Use the Content-length part of the header to know how many bytes will be received
  3. Receive the bytes of the previous step
  4. YOU MUST NOT CALL RECEIVE AGAIN. If you call Receive, your program will be blocked

Para recibir un HTTP Response o un HTTP Request usted debe:
  1. Recibir el Encabezado recibiendo datos hasta que se encuentre una línea vacía
  2. Usar la parte de Content-length del encabezado para conocer el número de bytes por recibir
  3. Recibir los bytes del paso anterior
  4. USTED NO DEBE LLAMAR RECEIVE OTRA VEZ. Si usted llama Receive su programa se bloqueará

Problem 4
Repeat the previous problem using Java. If you do not remember how to create a Java project, please review: Wintempla > Introduction > Java .
Repita el problema previo usando Java. Si usted no recuerda cómo crear un proyecto de Java, por favor repase: Wintempla > Introduction > Java .

WebBrowserJRun

WebBrowserJ.java
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.net.*;
import java.io.*;

public class WebBrowserJ extends JFrame
{
     private JTextArea tbxOutput;

     public WebBrowserJ()
     {
          this.setTitle("WebBrowserJ");
          this.setSize(600, 900);
          this.addWindowListener(new ExitListener());
          //________________________________ 1. Create GUI
          Container pane = this.getContentPane();
          pane.setLayout(new GridLayout());
          tbxOutput = new JTextArea(30, 70);
          pane.add(tbxOutput);
          //_____________________________________
          Socket socket = null;
          try
          {
               //________________________________ 2. Connect Socket
               socket = new Socket("www.google.com", 80);
               PrintWriter output = new PrintWriter(socket.getOutputStream(), true);
               BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
               //________________________________ 3. Send HTTP Request
               output.println("GET / HTTP/1.0\r\n");
               //________________________________ 4. Receive HTTP Response
               String line;
               while (true)
               {
                    line = input.readLine();
                    if (line == null) break;
                    tbxOutput.append(line + "\r\n");
               }
               socket.close();
          }
          catch(IOException ioe)
          {
               tbxOutput.append(ioe.toString()+"\r\n");
          }
          finally
          {
          }
     }
     public static void main(String[] args)
     {
          WebBrowserJ frame = new WebBrowserJ();
          frame.pack();
          frame.setVisible(true);
     }

     public class ExitListener extends WindowAdapter
     {
          public void windowClosing(WindowEvent e)
          {
               System.exit(0);
          }
     }
}


Problem 5
Repeat the previous problem using Android. If you do not remember how to create an Android project, please review: Wintempla > Android . DO NOT check AppCompatActivity when creating the project.
Repita el problema previo usando Android. Si usted no recuerda cómo crear un proyecto de Android, por favor repase: Wintempla > Android . NO marque la opción de AppCompatActivity al crear el proyecto.

WebBrowserARun

Step A
Edit the AndroidManifest.xml file so that your application can connect to the Internet.
Edite el archivo AndroidManifest.xml para que su aplicación se pueda conectar a la Internet.

WebBrowser_AndroidManifest_xml

Step B
Edit the activity_main.xml file to include a TextView called tbxOutput.
Edite el archivo activity_main.xml para incluir una TextView llamada tbxOutput.

WebBrowser_activity_main_xml

Step C
Edit the MainActivity.java file as shown.
Edite el archivo MainActivity.java como se muestra.

MainActivity.java
package com.selo.mybrowsera;

import android.os.StrictMode;
//import android.support.v7.app.AppCompatActivity;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;

public class MainActivity extends Activity {

     @Override
     protected void onCreate(Bundle savedInstanceState)
     {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_main);
          TextView tbxOutput = (TextView)findViewById(R.id.tbxOutput);
          //___________________________________ 1. Allow main thread to run sockets (Do not use in production)
          StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().permitNetwork().build());
          //___________________________________
          Socket socket = null;

          try
          {
               //____________________________________________________ 2. Connect Socket
               socket = new Socket("www.google.com", 80);
               PrintWriter output = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()),true);
               BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
               //____________________________________________________ 3. Send HTTP Request
               output.println("GET / HTTP/1.0\r\n");
               //____________________________________________________ 4. Receive HTTP Response
               String line;
               while (true){
                    line=input.readLine();
                    if(line==null) break;
                    tbxOutput.append(line+"\r\n");
               }
               socket.close();
          }
          catch (Exception e)
          {
               tbxOutput.append(e.toString());
          }
     }
}


Code 302 Found

To balance the load among several web servers, Code 302 is used to redirect the request to a different server. A Web server may reply with 302 Found and the location of the new page using Location: in the HEAD of an HTTP Response as illustrated in the figure.
Para balancear la carga entre varios servidores web, el código 302 es usado para re-direccionar la solicitud a un nuevo servidor. El servidor Web puede responder con 302 y la ubicación de la nueva página usando Location: en el encabezado (HEAD) de una HTTP Response como se ilustra en la figura.

Location

Code 301 Moved Permanently

The code 301 is sent from the server to redirect the request to the new location.
El código 301 es enviado por el servidor para re-direccionar la solicitud a la nueva ubicación.

META HTTP-EQUIV="Refresh"

Some web pages have a META tag in the head part of the document to redirect the page to another web page. In this case, you must inspect between the tags <head> and </head> to find the respective META tag. The URL="http://new_address" in the META tag has the new address of the resource. This tag can also to refresh a Web page every number of seconds.
Algunas páginas web tiene una etiqueta META en la parte head del documento para re-direccionar la página a otra página web. En este caso, usted debe inspeccionar entre las etiquetas <head> and </head> para encontrar la etiqueta META respectiva. El URL="http://new_address" en la etiqueta META tiene la nueva dirección del recurso. Esta etiqueta puede usarse para refrescar una página web cierto número de segundos.

Tip
Internet Explorer sends the following GET HTTP request to connect to Yahoo!. Some web servers will not send the correct HTTP response if the GET HTTP request does not include some specific information. For instance, some web server send customize web pages for each explorer (one page for Internet Explorer, another page for Google Chrome, etc.) In this request, Windows NT 6.1 (Windows 7, Windows Server 2008 R2 or Windows Home Server 2011).

GET / HTTP/1.0
Accept: text/html, application/xhtml+xml, */*
Accept-Language: en-US\r\nUser-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)
Accept-Encoding: gzip, deflate
Host: www.yahoo.com
Connection: Keep-Alive\r\n\r\n
Internet Explorer envía la siguiente solicitud de GET HTTP para conectarse a Yahoo!. Algunos servidores web no enviarán la respuesta correcta de HTTP si la solicitud de GET HTTP no incluye información específica. Por ejemplo, algunos servidores envían páginas web personalizadas para cada explorador (una página para Internet Explorer, otra página para Google Chrome, etc.) En esta solicitud, Windows NT 6.1 (Windows 7, Windows Server 2008 R2 o Windows Home Server 2011).

GET / HTTP/1.0
Accept: text/html, application/xhtml+xml, */*
Accept-Language: en-US\r\nUser-Agent: Mozilla/5.0 (compatible; MSIE 9.0;Windows NT 6.1; WOW64; Trident/5.0)
Accept-Encoding: gzip, deflate
Host: www.yahoo.com
Connection: Keep-Alive\r\n\r\n

Tip
This is another example of HTTP request. Observe the Host: element, this is a required element in HTTP 1.1.


GET /data/index.htm HTTP/1.0
Host: www.yahoo.com
Connection: close
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)
Accept-Charset: ISO-8859-1,UTF-8;q=0.7,*;q=0.7
Cache-Control: no-cache
Accept-Language: de,en;q=0.7,en-us;q=0.3

Este es otro ejemplo de una solicitud de HTTP. Observe el elemento Host:, este es un elemento requerido en HTTP 1.1.


GET /data/index.htm HTTP/1.0
Host: www.yahoo.com
Connection: close
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)
Accept-Charset: ISO-8859-1,UTF-8;q=0.7,*;q=0.7
Cache-Control: no-cache
Accept-Language: de,en;q=0.7,en-us;q=0.3

Tip
Be careful when using strings and sockets. Remember that a computer program uses UNICODE (wstring or wchar_t), thus, some socket functions will require converting the string. In Wintempla, you may use the functions in the Sys::Convert class to perform these conversions. Most text in the Internet uses UTF-8, thus, you must use Sys::Convert::UTF8ToWstring to convert from UTF-8 to wstring.
Tenga cuidado cuando use cadenas de texto y sockets. Recuerde que un programa de computadora usa UNICODE (wstring o wchar_t), así, algunas funciones de los sockets requerirán que usted convierta la cadena de texto. En Wintempla, usted puede usar las funciones en la clase Sys::Convert para realizar estas conversiones. La mayoría del texto en la Internet usa UTF-8, por lo tanto, usted debe usar Sys::Convert::UTF8ToWstring para convertir de utfUTF8 a wstring.

Problem 6
Create a dialog application called WebImage using Wintempla to download an image from web server that use HTTP (not HTTPS). A multi-line textbox must be used to display the progress of the HTTP transactions. An Image control must be used to display the Google logo that will be downloaded. As Google changes frequently its web main page, the output presented may be different from the output of your program.
  1. The program sends an HTTP Request for the default document in the Web server
  2. The program receives an HTTP Response (with code 302 Found) and extracts the new location from the re-direction
  3. The program splits the Location field in the header in: server name and resource
  4. The program sends another HTTP Request using the re-direction information. If it gets an HTTP Response with code 302 Found, it tries at the new location until it gets an HTTP Response with code 200 OK
  5. The program receives the HTML of the main page and tries to find the <img tag corresponding to an image in the web page
  6. The program sends an HTTP Request to get the image
  7. The program saves to a file the body of the HTTP Response
  8. The program shown (in an image control) the image

Cree una aplicación de diálogo llamada WebImage usando Wintempla para descargar una imagen desde un servidor web que use HTTP (no HTTPS). Una caja de texto de multi-líneas se debe usar para mostrar el progreso de las transacciones en HTTP. Use un control de Image para mostrar la imagen que se va a descargar.
  1. El programa envía una HTTP Request para solicitar el documento predeterminado
  2. El programa recibe una HTTP Response (con código 302 Found) y extrae la nueva ubicación desde la respuesta de re-dirección
  3. El programa divide el campo Location del encabezado en: el nombre del servidor y el recurso
  4. El programa envía otra HTTP Request usando la información de re-dirección. Si este recibe un HTTP Response con código 302 Found, este intenta a la nueva ubicación hasta que este consigue una HTTP Response con código de 200 OK
  5. El programa recibe el HTML de la página principal y trata de buscar la etiqueta <img que corresponde a alguna imagen en la página
  6. El programa envía una HTTP Request solicitando la imagen
  7. El programa guarda el body de la HTTP Response en un archivo
  8. El programa muestra (en un control de imagen) la imagen descargada

WebImageRun1

WebImageRun2

WebImage.h
#pragma once //______________________________________ WebImage.h
#include "Resource.h"
class WebImage: public Win::Dialog
{
public:
     WebImage()
     {
     }
     ~WebImage()
     {
     }
     bool GetImageSrc(const wstring& in_imageTag, wstring& out_src);
     . . .
};

WebImage.cpp
. . .
#include "stdafx.h" //________________________________________ WebImage.cpp
#include "WebImage.h"

int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE , LPTSTR cmdLine, int cmdShow){
     WebImage app;
     return app.BeginDialog(IDI_WEBIMAGE, hInstance);
}

void WebImage::Window_Open(Win::Event& e)
{
     wstring servername = L"www.ugto.mx";
     Sys::Socket socket;
     Web::HttpResponse httpResponse;
     //
     Web::HttpRequest httpRequest;
     httpRequest.method = L"GET";
     httpRequest.resource = L"/";
     httpRequest.head[L"Accept"] = L"text/html, */*";
     //
     wstring location;
     int count = 0;
     wstring headText;
     int result;
     //______________________________________________________________ 1. Find a server that response with code 200 OK
     while (count < 10)
     {
          //____________________________________________________________ 2. Connect
          if (socket.Connect(servername, 80) == SOCKET_ERROR)
          {
               this->MessageBox(socket.GetLastErrorDesc(), L"WebImage", MB_OK | MB_ICONERROR);
               return;
          }
          //____________________________________________________________ 3. Send HTTP Request
          result = socket.Send(httpRequest);
          if (result == SOCKET_ERROR)
          {
               this->MessageBox(socket.GetLastErrorDesc(), L"WebImage", MB_OK | MB_ICONERROR);
               return;
          }
          if (result == SOCKET_DISCONNECTED)
          {
               this->MessageBox(L"Connection terminated", L"WebImage", MB_OK | MB_ICONERROR);
               return;
          }
          socket.ShutdownSend();
          //___________________________________________________________ 4. Receive HTTP Response
          result = socket.Receive(httpResponse);
          if (result == SOCKET_ERROR || result == SOCKET_DISCONNECTED)
          {
               this->MessageBox(L"Unable to receive HTTP response", L"WebImage", MB_OK | MB_ICONERROR);
               return;
          }
          socket.Disconnect();
          httpResponse.GetHeadText(headText);
          tbxOutput.Text += headText;
          tbxOutput.Text += L"___________________________________________\r\n";
          //___________________________________________________________ 5. Check Code
          if (httpResponse.code == 200) //OK
          {
               break;
          }
          else if (httpResponse.code == 301) // Move Permanently
          {
          }
          else if (httpResponse.code == 302) // Found
          {
               if (httpResponse.GetHeaderValue(L"Location", location) == false)
               {
                    this->MessageBoxW(L"Unable to find location on HTTP Code 302", L"WebImage", MB_OK | MB_ICONERROR);
                    return;
               }
               if (httpResponse.SeparateLocation(location, servername, httpRequest.resource) == false)
               {
                    this->MessageBoxW(L"Error separating location", L"WebImage", MB_OK | MB_ICONERROR);
                    return;
               }
          }
          count++;
     }
     if (httpResponse.code != 200)
     {
          this->MessageBox(L"HTTP response code is not 200 OK", L"WebImage", MB_OK | MB_ICONERROR);
          return;
     }
     //______________________________________________________ 6. We get here when we have received HTML from the Web server
     const bool isUtf8 = httpResponse.IsUtf8();
     wstring html;
     httpResponse.body.GetText(html, isUtf8);
     tbxOutput.Text += html;
     tbxOutput.Text += L"\r\n";
     //_______________________________________________________ 7. Find <img ...>
     size_t imgBegin = html.find(L"<img ");
     if (imgBegin == std::string::npos)
     {
          this->MessageBox(L"Not found <img ", L"WebImage", MB_OK | MB_ICONERROR);
          return;
     }
     size_t imgEnd = html.find(L">", imgBegin);
     if (imgEnd == std::string::npos)
     {
          this->MessageBox(L"Not found >", L"WebImage", MB_OK | MB_ICONERROR);
          return;
     }
     //
     wstring imageTag;
     imageTag.assign(html.begin()+imgBegin, html.begin()+imgEnd);
     tbxOutput.Text += L"_________________________________________________________ \r\n";
     tbxOutput.Text += imageTag;
     tbxOutput.Text += L"\r\n";
     //_______________________________________________________ 8. Extract: src="/images/srpr/logo.png"
     wstring imageSrc;
     if (GetImageSrc(imageTag, imageSrc) == false)
     {
          this->MessageBox(L"Not found image src", L"WebImage", MB_OK | MB_ICONERROR);
          return;
     }
     tbxOutput.Text += L"_________________________________________________________ \r\n";
     tbxOutput.Text += imageSrc;
     tbxOutput.Text += L"\r\n";
     //______________________________________________________ 9. Send HTTP Request for image
     if (imageSrc[0] == '/') // /images/logo.png
     {
          httpRequest.resource = imageSrc;
     }
     else if (imageSrc[0] == 'h') // http://
     {
          Web::HttpResponse::SeparateLocation(imageSrc, servername, httpRequest.resource);
     }
     else
     {
          this->MessageBox(L"Invalid character in imageSrc", L"WebImage", MB_OK | MB_ICONERROR);
          return;
     }
     if (socket.Connect(servername, 80) == SOCKET_ERROR)
     {
          this->MessageBox(socket.GetLastErrorDesc(), L"WebImage", MB_OK | MB_ICONERROR);
          return;
     }
     result = socket.Send(httpRequest);
     if (result == SOCKET_ERROR || result == SOCKET_DISCONNECTED)
     {
          this->MessageBox(L"Unable to send HTTP Request for image", L"WebImage", MB_OK | MB_ICONERROR);
          return;
     }
     //______________________________________________________ 10. Receive HTTP Response for Google image
     result = socket.Receive(httpResponse);
     if (result == SOCKET_ERROR || result == SOCKET_DISCONNECTED)
     {
          this->MessageBox(L"Error receiving HTTP Request for image", L"WebImage", MB_OK | MB_ICONERROR);
          return;
     }
     socket.Disconnect();
     //______________________________________________________ 11. Save the image to a file
     if (httpResponse.code == 200)
     {
          if (httpResponse.body.SaveToFile(L"tmp.gif") == false)
          {
               this->MessageBox(L"Error saving image to file", L"WebImage", MB_OK | MB_ICONERROR);
               return;
          }
     }
     else
     {
          httpResponse.GetHeadText(headText);
          this->MessageBox(headText, L"Image HTTP Response", MB_OK | MB_ICONERROR);
          return;
     }
     //_______________________________________________________ 12. Display the image
     imgDisplay.FileName = L"tmp.gif"; // tmp.jpg or tmp.png
}

// Input: in_imageTag= "<img alt="Google" height="95" src="/images/srpr/logo.png" ...>"
// Output: out_src = "/images/srpr/logo.png
bool WebImage::GetImageSrc(const wstring& in_imageTag, wstring& out_src)
{
     . . .
     return true;
}

Manipulating data with Sockets

You can manipulate data for sockets using variables char or string; however be aware that the content of these variables may have zeros (NULL values). Thus, several functions to manipulate strings may not work properly, for instance strlen will not provide the bytes in a char* variable, instead you may store the number of bytes in a separated variable. Likewise, functions like strcat, strcpy, etc., will not operate correctly. When using string from the STL, you will have to be very careful when converting to char* using data.c_str(); in this case you will also need the number of bytes which you can accomplish using data.length().
Usted puede manipular datos para sockets usando variables char o string; sin embargo tenga en cuenta que el contenido de estas variables puede tener ceros (valores NULL). Así, varias funciones para manipular texto pueden no funcionar apropiadamente, por ejemplo strlen no proporcionará el número de bytes en una variable char*, en su lugar usted debe almacenar el número de bytes en una variables por separado. De igual forma, funciones como strcar, strcpy, etc., no operarán correctamente. Cuando use string de la STL, usted tendrá que tener mucho cuidado cuando convierta a char* usando data.c_str(); en este caso usted también necesitará el número de bytes lo cual puede lograr usando data.length().

Connection

An HTTP response or an HTTP request may have a parameter called Connection in their header. If the server sends an HTTP response with Connection: close, it means that the connection has been closed. In this case, if the client needs to send another request, then another socket connection must be created. On the other hand, if Connection: Keep-Alive is used, it means that the client can send another HTTP request using the same connection. Consider a client requesting a HTML document, if Connection: Keep-Alive is requested and the server answers with Connection: Keep-Alive, then the client may request images, scripts, styles sheets, etc., using the same connection saving a great amount of resources (see the example in the figure below).
Una respuesta de HTTP y una solicitud de HTTP pueden tener un parámetro llamado Connection en su encabezado. Si el servido envía una respuesta de HTTP con Connection: close, esto significa que la conexión ha sido cerrada. In este caso, si el cliente necesita enviar otra solicitud, entonces otra conexión por medio de sockets debe crearse. Por otro lado, si Connection: Keep-Alive es usado, esto significa que el cliente puede enviar otra solicitud de HTTP usando la misma conexión. Considere un cliente solicitando un documento de HTML, si Connection: Keep-Alive se solicita y el servidor contesta con Connection: Keep-Alive, entonces el cliente puede solicitar imágenes, scripts, hojas de estilo, etc., usando la misma conexión ahorrando una gran cantidad de recursos (vea el ejemplo en la figura de abajo).

ConnectionKeepAlive

Problem 7
Create file called MyRequest.htm to learn how to send an HTTP Request using Javascript. Create also the index.htm file as shown.
Cree un archivo llamado MyRequest.htm para aprender como enviar una solicitud de HTTP usando Javascript. Cree tambien el archivo index.htm como se muestra.

MyRequest.htm
<html>
<head>
     <script>
     var xmlHttp = null;
     if (window.XMLHttpRequest != null)
     {
          xmlHttp = new XMLHttpRequest();
     }
     else
     {
          xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
     }
     //if (xmlHttp == null) return;

     xmlHttp.onreadystatechange = function ()
     {
          //_______________________________________________________________Receive an HTTP Response
          //xmlHttp.readyState.1 The request has been set up
          //xmlHttp.readyState.2 The request has been sent
          //xmlHttp.readyState.3 The request is in process
          if (xmlHttp.readyState == 0) //xmlHttp.readyState = 0 The request is not initialized
          {
               alert('xmlHttp: The request is not initialized');
          }
          else if (xmlHttp.readyState == 4 && xmlHttp.status != 200) //xmlHttp.readyState = 4 The request is complete
          {
           alert('Invalid HTTP request\nxmlHttp.readyState=' + xmlHttp.readyState.toString() + '\nxmlHttp.status=' + xmlHttp.status.toString());
          }
          else if (xmlHttp.readyState == 4 && xmlHttp.status == 200) //xmlHttp.readyState= 4 The request is complete
          {
               //xmlHttp.responseXML.preserveWhiteSpace = true;
               //document.write(xmlHttp.responseText);
               alert(xmlHttp.responseText);
          }
     }
     //__________________________________________________________________ Send an HTTP Request
     //_________________________________________________ POST
     ////var body = "some data";
     //xmlHttp.open("POST", "http://localhost/index.htm", true);
     ////xmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
     ////xmlHttp.setRequestHeader('Content-Length', body.length);
     ////xmlHttp.send(body);
     //xmlHttp.send();
     //_________________________________________________ GET
     xmlHttp.open("GET", "http://localhost/index.htm", true);
     //xmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
     xmlHttp.setRequestHeader('Content-Length', '0');
     xmlHttp.send();
     </script>
</head>
<body>
</body>
</html>


Step A
Create also the index.htm file as shown.
Cree tambien el archivo index.htm como se muestra.

index.htm
<html>
<h1>Happy World</h1>
</html>


Step B
Copy and paste both files in the root folder of a Web Server.
Copie y pegue ambos archivos en la carpeta raíz de un Servidor Web.

WebPublish

Step C
Use any Web Browser to open the MyRequest.htm page. http://localhost/MyRequest.htm
Use cualquier Explorador Web para abrir la página MyRequest.htm. http://localhost/MyRequest.htm

MyRequestRun

Spoofing IP Address

Some web sites use the Forwarded HTTP header or the X-Forwarded-For HTTP header to find the client IP address. Once the site has the IP address, it is possible to find an approximately location of the client using an IP address database.
Algunos sitios web usan los encabezados de HTTP Forwarded o X-Forwarded-For para encontrar la dirección IP del cliente. Una vez que el sitio tiene una dirección de IP, es posible encontrar una ubicación aproximada del cliente usando una base de datos de datos de direcciones IP.

Server Variables

The table below shows a list of the Server Variables to retrieve information from the Web Server. In Wintempla call Web::HttpConnector::GetServerVariable to retrieve the value of the server variable.
La tabla mostrada debajo lista las Variables del Servidor para retraer información desde el Servidor Web. En Wintempla use la función Web::HttpConnector::GetServerVariable para retraer el valor de la variable del servidor.

ALL_RAW

All headers in raw form. The header names and values appear as they are sent by the client. Currently, this value is primarily used by proxy servers and other similar applications.

AUTH_PASSWORD

The value entered in the client's authentication dialog. This variable is only available if Basic authentication is used.

AUTH_TYPE

The type of authentication used. If the string is empty, then no authentication is used. Possible values are Basic or NTLM.

AUTH_USER

The value entered in the client's authentication dialog box.

CERT_FLAGS

If bit0 is set to 1, a client certificate is present. If bit1 is set to 1, the certification authority (CA) of the client certificate is invalid. That is, it is not on this server's list of recognized CAs.

CERT_ISSUER

The issuer field of the client certificate.

CERT_KEYSIZE

The number of bits in the Secure Sockets Layer (SSL) connection key size.

CERT_SECRETKEYSIZE

The number of bits in the server certificate private key.

CERT_SERIALNUMBER

The serial-number field of the client certificate.

CERT_SERVER_ISSUER

The issuer field of the server certificate.

CERT_SERVER_SUBJECT

The subject field of the server certificate.

CERT_SUBJECT

The subject field of the client certificate.

CONTENT_LENGTH

The number of bytes of data that the script or extension can expect to receive from the client. This total does not include headers.

CONTENT_TYPE

The content type of the information supplied in the body of a POST request.

HTTP_ACCEPT

The Accept header.

HTTPS

On if the request came in through secure channel (with SSL encryption), or off if the request is for an unsecure channel.

HTTPS_KEYSIZE

The number of bits in the SSL connection key size.

HTTPS_SECRETKEYSIZE

The number of bits in server certificate private key.

HTTPS_SERVER_ISSUER

The issuer field of the server certificate.

HTTPS_SERVER_SUBJECT

The subject field of the server certificate.

PATH_INFO

Additional path information, as given by the client. This consists of the trailing part of the URL after the script or ISAPI DLL name, but before the query string, if any.

PATH_TRANSLATED

The value of PATH_INFO, but with any virtual path expanded into a directory specification.

QUERY_STRING

The information that follows the first question mark in the URL that referenced this script.

REMOTE_ADDR

The IP address of the client or agent of the client (for example gateway, proxy, or firewall) that sent the request.

REMOTE_HOST

The host name of the client or agent of the client (for example, gateway, proxy or firewall) that sent the request if reverse DNS is enabled. Otherwise, this value is set to the IP address specified by REMOTE_ADDR.

REMOTE_USER

The user name supplied by the client and authenticated by the server. This comes back as an empty string when the user is anonymous.

REQUEST_METHOD

The HTTP request method verb.

SCRIPT_NAME

The name of the script program being executed.

SERVER_NAME

The server's host name, or IP address, as it should appear in self-referencing URLs.

SERVER_PORT

The TCP/IP port on which the request was received.

SERVER_PORT_SECURE

A string of either 0 or 1. If the request is being handled on the secure port, then this will be 1. Otherwise, it will be 0.

SERVER_PROTOCOL

The name and version of the information retrieval protocol relating to this request.

SERVER_SOFTWARE

The name and version of the Web Server under which the ISAPI extension DLL program is running.

URL

The base portion of the URL. Parameter values will not be included. The value is determined when the Web Server parses the URL from the header.

Tip
In a Web Wintempla application, you can set to true the variable showAllServerVariables to display the name and value of all server variables as shown in the code below. To see the actual values of these variables, your application must be published in a Microsoft IIS Web Server.
En una aplicación Web de Wintempla, usted puede fijar en true la variable showAllServerVariables para mostrar el nombre y el valor de todas las variables del servidor como se muestra en el código de abajo. Para ver el valor real de estas variables, su aplicación debe ser publicada en un Servidor Web de Microsoft IIS.

Problem 8
Create a Web Application using Wintempla called VariableList to display the Web Server variables. Use Wintempla to add a OK button and edit the Index.cpp file as shown.
Cree una Aplicación Web usando Wintempla llamada VariableList para mostrar las variables del Servidor Web. Use Wintempla para agregar un botón de y edite el archivo index.cpp como se muestra.

Index.cpp
. . .
#include "stdafx.h" //_____________________________________________ Index.cpp
#include "Index.h"

void Index::Window_Open(Web::HttpConnector& h)
{
}

void Index::btOK_onclick(Web::HttpConnector& h)
{
     this->showAllServerVariables = true;
}


ServerVariables

Step A
Publish your DLL in the server to see the values returned by Microsoft IIS.
Publique su DLL en el servidor para ver los valores regresados por Microsoft IIS.

VariableListServerRun

Problem 9
Edit the Index.cpp file of the previous problem as shown. Then, test the program.
Edit el archivo index.cpp del problema anterior como se muestra. Entonces, pruebe el programa.

Index.cpp
#include "stdafx.h" //_____________________________________________ Index.cpp
#include "Index.h"

void Index::Window_Open(Web::HttpConnector& h)
{
     h.httpCode = 401;
     //h.httpCode = 404;
}

void Index::btOK_onclick(Web::HttpConnector& h)
{
     this->showAllServerVariables = true;
}


© Copyright 2000-2021 Wintempla selo. All Rights Reserved. Jul 22 2021. Home