Simple HTTP client library for W7500x MCU

Overview

오늘은 얼마 전에 간단히 구현 해 본 HTTP client 예제 코드를 소개하려 합니다.

본 포스팅에서 소개하는 코드는 C언어로 Keil uvision 5 기반에서 작성 되었으며, WIZnet의 ARM Cortex-M0 기반 Ethernet MCU인 W7500x 기반에서 동작하도록 제작 되었습니다. 하지만 매우 간단하며, MCU 의존성이 거의 없기 때문에 WIZnet의 Hardwared TCP/IP core를 활용하는 경우라면 쉽게 포팅하여 활용 하실 수 있을 것 같습니다.

  • Link: WIZnet Wiki site –  W7500x Ethernet MCU (W7500 / W7500P)

 

overview.png

본 이미지는 포스팅 내용과 ‘약간’의 관련성이 있습니다 🙂

HTTP client는 웹 서버(HTTP server)와 연동하여 동작하는 단말을 구현하기 위해 널리 사용되고 있지만, 응용의 목적과 형태에 따라 다양한 Header와 Method, Content-Type을 사용하기에 필요에 따라 HTTP request packet을 생성하여 전송하는 정도로  활용 하고 있었습니다. 하지만 이러한 코드의 형태는 각기 다른 응용 코드 구현 시 매 번 HTTP protocol에 맞춰 packet을 생성해야 했기 때문에 재사용성이 매우 떨어지고, HTTP request를 전송하기 위한 protocol format을 온전히 파악해야 하는 단점이 있었습니다.

따라서, 관련 프로토콜에 대한 큰 지식 없이도 가능한 한 쉽게 접근 할 수 있는 형태의 HTTP client를 제작 해 보았습니다. 본 코드 예제는 지속적으로 개선 될 예정입니다.

 

Concept

  • 단순 HTTP request 전송이 아닌, 재사용성/일관성 있는 코드 구현
  • HTTP method: GET / HEAD / PUT / POST / DELETE 지원
  • Custom header field 추가 지원
  • Multipart/Form-data content type 지원 – Server로 파일 전송 기능 등
    • Example boundary string 포함 / 필요한 경우 수정
    • 파일 전송을 위한 usage는 준비 예정*
  •  REST API 활용을 위해 JSON 등 문자열 데이터의 첨부가 용이한 형태

 

 

Source Code

 

<httpClient.h>

#include <stdint.h>

#ifndef __HTTPCLIENT__
#define __HTTPCLIENT__

// HTTP client debug message enable
#define _HTTPCLIENT_DEBUG_

// Data buffer size
#ifndef DATA_BUF_SIZE
#define DATA_BUF_SIZE 2048
#endif

#define HTTP_CLIENT_PORT_MIN 0xB000 // 45056
#define HTTP_CLIENT_PORT_MAX 0xFFFF // 65535

/*********************************************
* HTTP Method String
*********************************************/
#define HTTP_GET "GET"
#define HTTP_HEAD "HEAD"
#define HTTP_POST "POST"
#define HTTP_PUT "PUT"
#define HTTP_DELETE "DELETE"


/*********************************************
* HTTP Content-Type String
*********************************************/
#define HTTP_CTYPE_MULTIPART_FORM "multipart/form-data"
#define HTTP_CTYPE_APP_HTTP_FORM "Application/x-www-form-urlencode"
#define HTTP_CTYPE_APP_JS "Application/javascript"
#define HTTP_CTYPE_APP_JSON "Application/json"
#define HTTP_CTYPE_APP_XML "Application/xml"
#define HTTP_CTYPE_TEXT_PLAIN "text/plain"
#define HTTP_CTYPE_TEXT_HTML "text/html"
#define HTTP_CTYPE_TEXT_CSS "text/css"
#define HTTP_CTYPE_TEXT_JS "text/javascript"
#define HTTP_CTYPE_TEXT_XML "text/xml"


/*********************************************
* HTTP Simple Return Value
*********************************************/
// Return value
#define HTTPC_FAILED 0
#define HTTPC_SUCCESS 1
#define HTTPC_CONNECTED 2
// Return value: boolean type
#define HTTPC_FALSE 0
#define HTTPC_TRUE 1


/*********************************************
* HTTP Requset Structure Initializer
*********************************************/
#define HttpRequest_multipart_post_initializer {(uint8_t *)HTTP_POST, NULL, NULL, (uint8_t *)HTTP_CTYPE_MULTIPART_FORM, (uint8_t *)"keep-alive", 0}
#define HttpRequest_get_initializer {(uint8_t *)HTTP_GET, NULL, NULL, NULL, (uint8_t *)"keep-alive", 0}


/*********************************************
* HTTP Boundary String for Multipart/form data
*********************************************/
#define formDataBoundary "----WebKitFormBoundaryE8pT6qqUHgRhSDDC" // example boundary string for multipart form data


// HTTP client structure
typedef struct __HttpRequest {
uint8_t * method;
uint8_t * uri;
uint8_t * host;
uint8_t * content_type;
uint8_t * connection;
uint32_t content_length;
} __attribute__((packed)) HttpRequest;

// HTTP client status flags
extern uint8_t httpc_isSockOpen;
extern uint8_t httpc_isConnected;
extern uint16_t httpc_isReceived;

// extern: HTTP request structure
extern HttpRequest request;


/*********************************************
* HTTP Client Functions
*********************************************/
uint8_t httpc_connection_handler(void); // HTTP client socket handler - for main loop, implemented in polling
uint8_t httpc_init(uint8_t sock, uint8_t * ip, uint16_t port, uint8_t * sbuf, uint8_t * rbuf); // HTTP client initialize
uint8_t httpc_connect(void); // HTTP client connect (after HTTP socket opened)
uint8_t httpc_disconnect(void);
uint16_t httpc_add_customHeader_field(uint8_t * customHeader_buf, const char * name, const char * value); // Function for adding custom header fields (httpc_send_header() function only)
uint16_t httpc_send_header(HttpRequest * req, uint8_t * buf, uint8_t * customHeader_buf, uint16_t content_len); // Send the HTTP header only
uint16_t httpc_send_body(uint8_t * buf, uint16_t len); // Send the HTTP body only (have to send http request body after header sent)
uint16_t httpc_send(HttpRequest * req, uint8_t * buf, uint8_t * body, uint16_t content_len); // Send the HTTP header and body
uint16_t httpc_recv(uint8_t * buf, uint16_t len); // Receive the HTTP response header and body, User have to parse the received messages depending on needs

#endif

 

 

Usage Example

  • HTTP Get Request
    • 간단한 HTTP GET request의 Usage를 이미지로 첨부
    • 상세한 내용과 함수 소개 보완 예정

 

usage_1_getRequest.png

 

 

 

 

 

Advertisements

답글 남기기

아래 항목을 채우거나 오른쪽 아이콘 중 하나를 클릭하여 로그 인 하세요:

WordPress.com 로고

WordPress.com의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

Twitter 사진

Twitter의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

Facebook 사진

Facebook의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

Google+ photo

Google+의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

%s에 연결하는 중