axis2 默认端口_基于 AXIS2/C 的 C 语言库实现对提供 REST API 的系统进行数据访问...
基于 AXIS2/C 的 C 語言庫實現對提供 REST API 的系統進行數據訪問
宋 東平 和 趙 健
2013 年 3 月 07 日發布
AXIS2/C 簡介和 REST 及 REST API 相關內容的簡介
AXIS2/C 簡介
Axis2/c 是基于 C 語言實現的 Web Service 引擎,基于 Axis2 架構,用于提供 Web 服務,并具有良好的可移植性,可以作為其他軟件的一部分提供 Web 服務。Axis2/c 支持 SOAP1.1 及 SOAP1.2 協議,并且支持 RESTful 風格的 Web 服務?;?Axis2/c 開發的 Web 服務可以同時暴露為 SOAP 和 RESTful 風格的服務。用戶可以基于 Axis2/c,開發 Web 服務以供其他客戶端進行調用,亦可通過調用 Axis2/c 提供的 C 語言庫,開發客戶端程序,去訪問其他的 Web 服務。
REST 及 REST API 簡介
REST(REpresentational State Transfer,表述性狀態轉移),指一組架構約束條件和原則,是當下 Web Service 領域流行的一種軟件架構風格。REST 強調從資源的角度觀察整個網絡,基于 REST 的架構是一種面向資源的架構(Resource-Oriented Architecture,ROA)。資源通常由唯一的 URI(Uniform Resource Identifier,統一資源標識符)來標識,例如:"http://10.11.12.13:8080/rest/resources/Server"。客戶端的程序通過訪問 URI 來獲取資源的表述。REST 通常使用 HTTP,URI,XML 以及 HTML 這些現有的廣泛流行的協議和標準。
基于 REST 的 Web 服務以其架構簡單、可擴展、安全有效,通過 HTTP 直接傳播數據等特性,成為 Web 服務領域一個越來越流行的架構形式。
REST API 是一個系統提供給外部系統的數據訪問服務接口?;?REST API 的服務,以資源的形式存在 ,客戶端通過對資源的操作實現相應的功能。在 RESTful 的 Web 服務中,對資源的操作通過 HTTP 的四個標準方法實現,且所有的業務需求均可映射成對資源的操作。例如,獲取資源的表述用 GET 方法,修改資源用 PUT 方法,添加一個資源用 POST 方法 或者 用 PUT 方法(POST 表示創建子資源,PUT 在目標資源不存在時創建資源本身),刪除資源用 DELETE 方法等。支持 HEAD 操作,但它只返回報頭,不返回表述,用于得到資源的元數據時使用。
HTTP 通信過程中,身份認證 Authentication 的分析
在 HTTP 通信過程中,認證是一種用來允許 Web 瀏覽器,或者其他客戶端程序在請求時提供以用戶名及密碼形式的憑證。HTTP 認證基于質詢 / 回應 (challenge/response) 的認證模式,并主要支持兩種認證方式:基本認證 (basic authentication) 以及摘要認證 (digest authentication),下面主要分析基本認證的步驟。
通常情況下,客戶端第一次請求 URI 服務時,不知曉是否需要驗證,因此會發送不帶認證信息的 HTTP 請求,服務端由于找不到認證信息,認證失敗,向客戶端發送一個 HTTP 響應,狀態碼為 401(Unauthorized),并包含 WWW-Authenticate 消息頭,客戶端收到 HTTP 響應后,重新發送 HTTP 請求,并在請求頭中添加 Authorization 消息頭,格式為 Authorization:credentials,其中 credentials 是認證信息,具體認證信息根據不同的認證方案而不同,當服務器對認證信息進行判斷,通過后即響應客戶端請求,如下顯示了基本認證的步驟:客戶端訪問一個受 HTTP 基本認證保護的資源。
服務器返回 401 狀態,要求客戶端提供用戶名和密碼進行認證。
401 UnauthorizedWWW-Authenticate:Basic realm="Secret World"
客戶端將輸入的用戶名密碼用 Base64 進行編碼后,采用非加密的明文方式傳送給服務器:Authorization:Basic xxxxxx(其中 xxxxxx 為 username:password 通過 Base64 編碼的字符串),例如:Authorization:Basic dXNlcm5hbWU6cGFzc3dvcmQ=
如果認證成功,則返回相應的資源。如果認證失敗,則仍返回 401 狀態,要求重新進行認證。
AXIS2/C 環境搭建
AXIS2/C 環境搭建(Linux 環境)
這里我們以 Red Hat 5.7 環境為例,介紹一下如何搭建 Axis2/c 的運行環境。首先需要下載 Axis2c 的安裝包,下載地址可見參考資料。這里我們以最新的版本 1.6 為例。創建安裝目錄 axis2c,解壓縮 Axis2/c 的安裝包 axis2c-src-1.6.0.tar.gz 到文件夾 axis2c-src-1.6.0 下,如下圖所示:
圖 1. 解壓縮 AXIS2/C 安裝包
解壓之后,編譯源碼進行安裝。參數 prefix 用來指定安裝目錄,enable-openssl 用來指定是否需要訪問具有 SSL 的 REST API 系統。如下圖所示:
圖 2. 編譯并安裝
Axis2/c 的安裝包當中提供了很多用例,用例當中使用到了某些環境變量,所以這里我們需要設定兩個環境變量:
export AXIS2C_HOME=/zhaojian/axis2c // 指定 Axis2c 的安裝目錄
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${AXIS2C_HOME}/lib/ // 指定 Axis2c 的 library 目錄
用例代碼也需要進行編譯安裝。如下圖所示:
圖 3. 編譯用例代碼
至此,基本的 Axis2/c 開發運行環境已經搭建完成,接下來,運行示例代碼,并測試運行環境是否可以正常運行。用例代碼是運行在 Axis2/c Server 之上的,所以必須先啟動 Axis2/c Server,先看一下啟動命令的幫助信息,如下圖所示:
圖 4. 啟動命令的幫助信息
啟動方法,如下圖所示:
圖 5. 啟動 AXIS2/C Server 成功
如果輸入服務器啟動命令”./axis2_http_server”之后,命令行一直處于 hang on 的狀態,表明 Server 已經啟動成功,用例代碼可以運行了;如果命令行中斷退出如下圖所示,表明啟動失敗,可以通過日志文件 axis2.log 找出失敗原因。本實例中導致失敗的原因是 Axis2/c Server 服務器的默認端口 9090 被其它應用程序占用,導致啟動失敗。
圖 6. 啟動 AXIS2/C Server 失敗
我們可以通過使用啟動命令參數 -p 來修改端口號,如下圖所示:
圖 7. 修改端口
Axis2c Server 啟動之后,就可以運行用例代碼了:
圖 8. 運行用例代碼
這里要指出的是因為啟動 Server 時,如果修改了默認端口 9090 為其它端口比如 8080 時,當運行用例比如上圖中的 echo 命令時,也需要修改用例當中的端口為已修改的端口號 8080(可以通過命令 echo 的參數來修改,也可以修改用例源代碼,不過需要重新編譯安裝)。
AXIS2/C 的參數配置
為了能夠通過 Axis2/c 提供的 C 語言庫函數來訪問具有 REST API 接口的系統數據,我們必須對 Axis2/c 的環境做一些參數配置,才能夠讓我們的 Sample Code 順利運行。在 Axis2/c 中,所有 Axis2/c 啟動需要的配置都包括在配置文件 axis2.xml 當中。下面我們來看看都有哪些參數可以修改來滿足我們的示例代碼。
首先如果用戶需要訪問或編寫 RESTful 風格的 Web Service,都需要將參數“enableREST”更改為“true”,默認值已經設為“true”如下圖所示:
圖 9. 啟用 REST 功能
默認情況下,Axis2/c 使用 HTTP 協議進行服務訪問,對于提供了安全層的服務訪問,這里需要啟用 HTTPS 協議的配置,首先確認安裝部署了 Axis2/c 服務的機器上是否安裝 openssl 以便我們進行 HTTPS 的數據訪問,確認方法如下圖所示,確保 openssl 包已安裝即可:
圖 10. 為 Axis2/c 添加 SSL 支持
在 axis2.xml 當中啟用如下幾個參數:
圖 11. 啟用 HTTPS 參數
另外,在訪問具有 HTTPS 的服務時,服務端需要驗證客戶端的證書,所以我們還需要提供訪問證書的路徑信息,比如:
圖 12. 證書路徑
查看服務端的證書的代碼的命令是 openssl s_client – connect :. 請看如下圖示例所示:
圖 13. 查看服務端證書
可以通過下面這三條命令在默認目錄下生成本地證書 ( 可參考下圖所示 ):echo |\
openssl s_client -connect : 2>&1 |\
sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > cert.pem
其中 和 是所要訪問的提供 REST API 系統的 IP 地址和端口。
圖 14. 制作本地證書
在 HTTP 通信過程中,部分 Web 服務需要驗證訪問該服務的用戶身份,可以通過修改 axis2.xml 中的參數實現,也可以通過在代碼中增加相應語句實現(后續章節會具體講解),需要修改參數如下:
圖 15. 添加 Authentication 信息
做完以上這些參數配置之后,如果一開始編譯源碼時,就添加了參數 enable-openssl 并且值為 yes,我們這里就不需要重新編譯源碼了,只需要重新啟動 Axis2 Server 就可以了,否則需要重新編譯并且添加參數 enable-openssl 為 yes 值。
標準 REST API 方法的訪問
REST API 訪問過程解析
對于提供了 REST API 服務的系統進行數據請求調用是基于 HTTP 協議進行通信的,并且使用了標準的 HTTP 方法 GET,POST,PUT,DELETE 等。本節通過實例代碼,詳細介紹如何通過 Axis2/c 提供的庫函數,使用 C 語言代碼,完成 REST 請求消息的創建,訪問 REST API 服務的標準方法實現以及對于響應消息的接收等內容。
在接下來的實例清單和 Sample Code 當中,我們都以 IBM Systems Director 產品提供的 REST API 服務為例,所涉及到的 URI 信息也會以該服務提供的內容為例。該產品提供的 RES API 詳情可見參考資料。
創建一個完整的請求消息,包括三個部分:請求行、消息頭以及請求體。請求行可以通過兩種方法實現。第一種是通過符合要求的請求行字符串,調用 axis2_http_request_line.h 中 axis2_http_request_line_parse_line 方法,生成請求行,如清單 1 所示:
清單 1. 請求行創建方式一axis2_http_request_line_t *request_line = NULL;
const char *request_line_str = "GET /ibm/director/rest/resources HTTP/1.1\r\n";
request_line = axis2_http_request_line_parse_line(env, request_line_str);
第二種是調用 axis2_http_request_line.h 中 axis2_http_request_line_create 方法,通過傳遞必要參數,創建請求行,如清單 2 所示:
清單 2. 請求行創建方式二axis2_http_request_line_t *request_line = NULL;
request_line =
axis2_http_request_line_create(env, "GET", "/ibm/director/rest/resources", "HTTP/1.1");
消息頭的創建可以通過調用 axis2_http_header.h 中的 axis2_http_header_create 方法進行創建,具體實例如清單 3 所示:
清單 3. 消息頭的創建axis2_http_simple_request_t *request = NULL;
axutil_url_t *url = NULL;
axis2_http_header_t *header = NULL;
request = axis2_http_simple_request_create(env,request_line,NULL,0 ,request_body);
url =
axutil_url_create(env, "https", "10.11.12.13",8422,"/ibm/director/rest/resources");
header = axis2_http_header_create(env, "Host", axutil_url_get_host(url, env));
axis2_http_simple_request_add_header(request, env, header);
在調用 REST API 過程中,部分通信需要驗證請求客戶端的身份??蛻舳丝梢酝ㄟ^在請求消息的消息頭中,添加屬性 Authentication,向服務端傳送身份認證信息。本例實現的認證為 HTTP 的基本認證,Authentication 屬性值的形式為 Basic xxxxxx 形式,xxxxxx 代表 username:password 通過 base64 編碼后的字符串,形如:Authorization:Basic dXNlcm5hbWU6cGFzc3dvcmQ=,可以通過調用 axutil_base64.h 中的 axutil_base64_encode 完成對字符串的編碼,請參閱清單 4 所示:
清單 4. Base64 編碼實現及 Authentication 屬性添加/***** 對 username:password 字符串進行編碼 *********/
int str_size = 0;
int encoded_len = 0;
axis2_char_t *str_src = "username:password";//“用戶名 : 密碼”字符串
axis2_char_t *encoded_str = NULL;// 對“用戶名 : 密碼”字符串進行 base64 編碼后字符串
axis2_char_t *firstStr = "Basic";//Authentication 值的頭部分
str_size = strlen(str_src);
encoded_len = axutil_base64_encode_len(str_size);
encoded_str = AXIS2_MALLOC(env->allocator, encoded_len + 2);
encoded_len = axutil_base64_encode(encoded_str,str_src,str_size);
/*****Authentication 值的合成 *********/
int size = 0;
int firstStrSize = strlen(firstStr);
int encoded_strSize = strlen(encoded_str);
size = firstStrSize + encoded_strSize;
if(firstStrSize > encoded_strSize){
size = ((int)strlen(firstStr)) * 2;
}else{
size = ((int)strlen(encoded_str)) * 2;
}
char *str_return = (char *) malloc((size + 2) * sizeof(char));
strcpy(str_return, firstStr);
strcat(str_return," ");
strcat(str_return, encoded_str);
/***** 在消息頭中添加屬性 Authentication*********/
header = axis2_http_header_create(env, "Authorization", str_return);
axis2_http_simple_request_add_header(request, env, header);
在調用 REST API 過程中,如果使用 POST 或 PUT 方法,需要向服務端傳遞相應信息,這些信息可以添加至請求消息中的消息體中。本例中,創建的消息體是基于 JSON 格式的,創建消息體的方式有兩種:
第一種方式是按照標準的 JSON 格式,直接書寫字符串,具體實例參照清單 5 所示,示例 JSON 格式消息體為:{"IPAddress":["192.168.1.1"]}。
清單 5. 消息體創建方式一char *body_request = NULL;
int body_request_len = 0;
body_request = "{\"IPAddress\":[\"192.168.1.1\"]}";
body_request_len = strlen(body_request);
第二種方式是通過調用 cJSON.h 中的方法,生成消息體,具體實例參照清單 6 所示,示例 JSON 格式消息體為:{"entry",{"name":"Andrew","phone":"555 123 456"}}。
清單 6. 消息體創建方式二char *body_request = NULL;
int body_request_len = 0;
cJSON *root;
cJSON *value;
cJSON *entry;
root=cJSON_CreateObject();// 定義根節點
entry = cJSON_CreateObject();
cJSON_AddItemToObject(root,"entry",entry);// 創建 JSON 數據:name 為 entry ,value 儲存在 entry 中
value = cJSON_CreateString("Andew");// 將字符串創建為 cJSON 數據
cJSON_AddItemToObject(entry,"name",value);
value = cJSON_CreateString("555 123 456");
cJSON_AddItemToObject(entry,"phone",value);
body_request = cJSON_Print(root);// 將 JSON 數據轉化為字符串;
body_request_len = strlen(body_request);
最后通過調用 axutil_stream.h 中的 axutil_stream_write 方法將需要添加的消息體字符串寫入消息體中,如清單 7 所示。
清單 7. 將字符串寫入消息體axutil_stream_t *request_body = NULL;
axutil_stream_write(request_body,env,body_request,body_request_len);// 寫入消息體
清單 8 詳細寫出了一個完整的請求發送,響應接收過程中方法的調用,涉及到的方法均包含在文件 axis2_http_client.h 中。
清單 8. REST API 服務的請求與響應過程axis2_http_simple_request_t *request = NULL;
request = axis2_http_simple_request_create(env, request_line,NULL,0 , request_body);
int status = 0;
axis2_http_client_set_server_cert(client, env, "/home/cert.pem");
// 對于 https,需要添加服務器端的證書,即之前制作的證書 cert.pem
axis2_http_client_send(client, env, request, NULL);
axis2_http_simple_response_t *response = NULL;
char *body_bytes = NULL;
int body_bytes_len = 0;
response = axis2_http_client_get_response(client, env);
body_bytes_len =
axis2_http_simple_response_get_body_bytes(response, env, &body_bytes);
// 其中 body_bytes 即為返回響應的結果字符串
四種方法對 REST API 的訪問實例
對于 REST API 服務,客戶端主要通過標準方法對資源進行訪問及處理,標準方法主要包括四種:GET、PUT、POST 以及 DELETE。下面將分別介紹這四種方法的使用。
GET 操作會列出該服務所提供的相關數據信息,實現 GET 操作的完整示例可以下載我們的 Sample Code,參考文件 rest_sample.c 當中的 test_rest_get 方法。運行該方法后可以得到類似于如下圖所示的運行結果:
圖 16. GET 操作運行結果
POST 操作可以通過消息體中含有的信息,執行資源的創建。實現 POST 操作完整示例可以下載我們的 Sample Code,參考文件 rest_sample.c 當中的 test_rest_post 方法。運行該方法后可以得到類似于如下圖所示的運行結果:
圖 17. POST 操作運行結果
PUT 操作主要用于對資源進行修改,需要修改的內容包含在 requestBody 中。實現 PUT 操作完整示例可以下載我們的 Sample Code,參考文件 rest_sample.c 當中的 test_rest_put 方法。運行該方法后可以得到類似于如下圖所示的運行結果:
圖 18. PUT 操作運行結果
DELETE 操作主要用于對資源進行刪除。實現 DELETE 操作完整示例可以下載我們的 Sample Code,參考文件 rest_sample.c 當中的 test_rest_delete 方法。運行該方法后可以得到類似于如下圖所示的運行結果:
圖表 19 DELETE 操作運行結果
Figure xxx. Requires a heading
另外,附上清單 9,常用狀態碼列表清楚的列出了各個返回碼的含義,方便讀者查閱:
清單 9. 常用狀態碼列表200 :表示服務器成功執行了客戶端的 HTTP/HTTPS 請求
201 :表示服務器按客戶端的請求成功創建了一個新資源
202 :表示服務器成功接收客戶端請求并進行處理
204 :表示服務器已經成功處理了客戶端請求,但是沒有可返回的內容
303:表示服務器將客戶端的請求重定向到另一個 URI,要完成請求必須進行進一步操作
304 :表示請求資源不能被更改
400 :表示客戶端的請求參數不合法或沒有表達足夠的信息
401 :表示因為安全的原因,導致對資源的操作沒有完成
404 :表示客戶端請求的資源不存在,即 URI 無效
405 :表示請求的資源不支持該操作
409 :表示 URI 指定的資源發生沖突
500 :表示服務器端發生非預期情況,導致請求沒有完成
503 :表示處理請求的服務目前不可用
C 語言對于 JSON 格式數據的處理
JSON(JavaScript Object Notation) 是一種輕量級的數據交換格式,采用完全獨立于語言的文本格式,易于人的閱讀和編寫,也易于機器的解析和生成,這些特性使 JSON 成為理想的數據交換語言。
在我們的 Sample Code 當中,使用基于 Axis2/c 的 C 語言庫來訪問 REST API 時,通過 GET 方法獲取到的數據就是 JSON 格式的數據。由于 Axis2/c 的庫函數中,目前還沒有對 JSON 格式數據處理的方法,所以下面我們將簡要介紹如何使用開源工具 cJSON 來完成對 JSON 格式數據的處理。
下面一個例子介紹了使用方法 cJSON_Parse 來解析 JSON 數據字符串并轉成數據對象 cJSON,通過 cJSON_GetObjectItem 方法得到你想要的數據項。請看清單 10 所示:
清單 10. 將 JSON 字符串轉換為數據對象 cJSONchar *document =
"{\"entry\":{\"name\":\"Andew\",\"phone\":\"555 123 456\"}}";
char *result = NULL;
cJSON *root;
cJSON *label;
root = cJSON_Parse(document);// 將字符型數據轉換為 cJSON 型
label = cJSON_GetObjectItem(root,"entry");// 通過已知的名稱,得到對應值
result = cJSON_Print(label);// 將 cJSON 數據轉換成 char 型
printf("the result is %s\n",result); // 打印輸出結果
使用 cJSON_Print 方法把 cJSON 數據對象 label 轉換為字符串,結果如下圖所示:
圖 . 20 JSON 字符串轉化
當然,你也可以使用 cJSON.h 當中的方法來創建 JSON 格式的數據字符串。首先使用方法 cJSON_CreateObject 來創建根節點,然后使用 cJSON_AddItemToObject 添加你想創建的數據項。下面一個例子就是如何生成 JSON 字符串 {"entry ":{"name":"Andrew","phone":"555 123 456"} }。請看清單 11 所示:
清單 11. 使用 cJSON 當中的方法創建 JSON 數據cJSON *root = cJSON_CreateObject();// 定義根節點
cJSON *entry = cJSON_CreateObject();// 定義 entry 節點
cJSON *value = cJSON_CreateString("Andew");// 將字符串創建為 cJSON 數據
cJSON_AddItemToObject(root, "entry",entry);// 創建 JSON 數據:name 為 entry ,value 儲存在 entry 中,
cJSON_AddItemToObject(entry,"name", value);
value = cJSON_CreateString("555 123 456");
cJSON_AddItemToObject(entry, "phone", value);
char *result = cJSON_Print(root);// 將 JSON 數據轉化為字符串;
printf("the result is :%s\n",result); // 打印輸出結果
使用 cJSON_Print 方法把 cJSON 數據對象 root 轉換為
字符串并打印出來,結果如下圖所示:
圖 21. JSON 數據創建
在 Sample Code 當中,我們列出來一段完整的代碼包括使用
cJSON和實例代碼的編譯:
Sample Code 當中使用了開源工具 cJSON,為了能夠運行 Sample Code,必須對 Sample Code 和 cJSON 的源碼進行編譯。編譯過程中會出現錯誤,主要由于以下兩個原因:1)cJSON 代碼中使用了 math.h 當中的函數所導致的,可以通過修改 Makefile 當中的” CC = gcc”為” CC = gcc -lm”即可;2)cJSON 代碼中的注釋格式使用不當所導致,可以通過修改 cJSON.c 文件,將” // “格式的注釋改為”/* */”即可。
Axis2/c 的 C 語言庫函數來訪問具有 REST API 系統獲取數據,
并使用 cJSON.h 當中的方法來處理返回的結果等 ( 可參考方法 test_rest_get 當中處理返回結果的代碼 )。詳細內容請參考我們
的 Sample Code,這里就不再一一敘述了。
結束語
REST API 提供非常簡潔的數據訪問接口,通過本文上述的示例,我們能夠使用 Axis2/c 的 C 語言庫,方便的訪問提供了 REST API 的系統。這也是方便了我們對一些 C 語言系統需要訪問 REST API 接口的支持。
下載資源樣例代碼 (sample.zip | 4KB)
相關主題Apache Axis2/c:開源軟件 Apache Axis2/C 官網首頁。
Axis2/c 環境搭建(Windows 環境):搭建 Windows 系統下 Axis2/c 開發環境。
Axis2/c 軟件包:Axis2/c 軟件包下載地址,本例使用的軟件包為 axsi2c-src-1.6.0.tar.gz。
Axis2/c 附加功能配置:在 Axis2/c 基本功能基礎上,提供了很多額外的功能,根據不同的需要,請參閱安裝手冊。
OpenSSL 安裝詳解:詳細介紹 OpenSSL 的安裝與配置過程。
REST,Web 服務,REST-ful 服務:詳細介紹 REST 架構原理以及 RESTful 風格的 Web Service。
HTTP 狀態碼:詳細介紹了 HTTP 通信過程中產生各種狀態碼的含義。
cJSON 源碼包:下載 cJSON 源碼包。
隨時關注 developerWorks 技術活動和網絡廣播。
訪問 developerWorks Open source 專區獲得豐富的 how-to 信息、工具和項目更新以及最受歡迎的文章和教程,幫助您用開放源碼技術進行開發,并將它們與 IBM 產品結合使用。
總結
以上是生活随笔為你收集整理的axis2 默认端口_基于 AXIS2/C 的 C 语言库实现对提供 REST API 的系统进行数据访问...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: doremi服务器可以导出文件,Dore
- 下一篇: cad多个窗口并排显示_你早该这么做!并