ballerina 学习二十 http/https
提供http && https server && client 访问功能
client endpoint
说白了就是http client
- 参考代码
import ballerina/http;
import ballerina/log;endpoint http:Client clientEndpoint {
url: "https://postman-echo.com"
};function main(string... args) { http:Request req = new;
var response = clientEndpoint->get("/get?test=123"); match response {
http:Response resp => {
log:printInfo("GET request:");
var msg = resp.getJsonPayload();
match msg {
json jsonPayload => {
log:printInfo(jsonPayload.toString());
}
error err => {
log:printError(err.message, err = err);
}
}
}
error err => { log:printError(err.message, err = err); }
}
req.setPayload("POST: Hello World"); response = clientEndpoint->post("/post", request = req);
match response {
http:Response resp => {
log:printInfo("\nPOST request:");
var msg = resp.getJsonPayload();
match msg {
json jsonPayload => {
log:printInfo(jsonPayload.toString());
}
error err => {
log:printError(err.message, err = err);
}
}
}
error err => { log:printError(err.message, err = err); } }
json jsonMsg = { method: "PUT", payload: "Hello World" };
req.setJsonPayload(jsonMsg); response = clientEndpoint->put("/put", request = req);
match response {
http:Response resp => {
log:printInfo("\nPUT request:");
var msg = resp.getJsonPayload();
match msg {
json jsonPayload => {
log:printInfo(jsonPayload.toString());
}
error err => {
log:printError(err.message, err = err);
}
}
}
error err => { log:printError(err.message, err = err); }
}
xml xmlMsg = xml `<request>
<method>PATCH</method>
<payload>Hello World!</payload>
</request>`;
req.setXmlPayload(xmlMsg); response = clientEndpoint->patch("/patch", request = req);
match response {
http:Response resp => {
log:printInfo("\nPATCH request:");
var msg = resp.getJsonPayload();
match msg {
json jsonPayload => {
log:printInfo(jsonPayload.toString());
}
error err => {
log:printError(err.message, err = err);
}
}
}
error err => { log:printError(err.message, err = err); }
} req.setPayload("DELETE: Hello World");
response = clientEndpoint->delete("/delete", request = req);
match response {
http:Response resp => {
log:printInfo("\nDELETE request:");
var msg = resp.getJsonPayload();
match msg {
json jsonPayload => {
log:printInfo(jsonPayload.toString());
}
error err => {
log:printError(err.message, err = err);
}
}
}
error err => { log:printError(err.message, err = err); }
} req.setPayload("CUSTOM: Hello World");
response = clientEndpoint->execute("COPY", "/get", req); req = new;
req.addHeader("Sample-Name", "http-client-connector");
response = clientEndpoint->get("/get", request = req);
match response {
http:Response resp => {
string contentType = resp.getHeader("Content-Type");
log:printInfo("\nContent-Type: " + contentType); int statusCode = resp.statusCode;
log:printInfo("Status code: " + statusCode); }
error err => { log:printError(err.message, err = err); }
}
}
- 输出结果
2018-06-01 21:03:32,032 INFO [] - GET request:
2018-06-01 21:03:32,059 INFO [] - {"args":{"test":"123"},"headers":{"host":"postman-echo.com","user-agent":"ballerina/0.970.1","x-forwarded-port":"443","x-forwarded-proto":"https"},"url":"https://postman-echo.com/get?test=123"}
2018-06-01 21:03:32,633 INFO [] -
POST request:
2018-06-01 21:03:32,636 INFO [] - {"args":{},"data":"POST: Hello World","files":{},"form":{},"headers":{"host":"postman-echo.com","content-length":"17","content-type":"text/plain","user-agent":"ballerina/0.970.1","x-forwarded-port":"443","x-forwarded-proto":"https"},"json":null,"url":"https://postman-echo.com/post"}
2018-06-01 21:03:33,349 INFO [] -
PUT request:
2018-06-01 21:03:33,351 INFO [] - {"args":{},"data":{"method":"PUT","payload":"Hello World"},"files":{},"form":{},"headers":{"host":"postman-echo.com","content-length":"40","content-type":"application/json","user-agent":"ballerina/0.970.1","x-forwarded-port":"443","x-forwarded-proto":"https"},"json":{"method":"PUT","payload":"Hello World"},"url":"https://postman-echo.com/put"}
2018-06-01 21:03:33,861 INFO [] -
PATCH request:
2018-06-01 21:03:33,863 INFO [] - {"args":{},"data":"<request>\n <method>PATCH<\/method>\n <payload>Hello World!<\/payload>\n <\/request>","files":{},"form":{},"headers":{"host":"postman-echo.com","content-length":"145","content-type":"application/xml","user-agent":"ballerina/0.970.1","x-forwarded-port":"443","x-forwarded-proto":"https"},"json":null,"url":"https://postman-echo.com/patch"}
2018-06-01 21:03:34,373 INFO [] -
DELETE request:
2018-06-01 21:03:34,375 INFO [] - {"args":{},"data":"DELETE: Hello World","files":{},"form":{},"headers":{"host":"postman-echo.com","content-length":"19","content-type":"text/plain","user-agent":"ballerina/0.970.1","x-forwarded-port":"443","x-forwarded-proto":"https"},"json":null,"url":"https://postman-echo.com/delete"}
2018-06-01 21:03:35,193 INFO [] -
Content-Type: application/json; charset=utf-8
2018-06-01 21:03:35,193 INFO [] - Status code: 200
http client redirect
redirect 是服务器端的相应,一般http 客户端不会进行处理,ballerina 有可选的配置参数,同时可以设置最大次数(防止死循环)
- 参考代码
import ballerina/io;
import ballerina/http;
import ballerina/log;
import ballerina/mime;endpoint http:Client clientEP {
url: "http://localhost:9090",
followRedirects: { enabled: true, maxCount: 5 }
};
function main(string... args) {
var returnResult = clientEP->get("/redirect1");
match returnResult {
error connectionErr => log:printError("Error in connection",
err = connectionErr);
http:Response resp => {
match resp.getTextPayload() {
error e => log:printError("Error in payload", err = e);
string payload => io:println("Response received : " + payload);
}
}
}
}
@http:ServiceConfig {
basePath:"/redirect1"
}
service<http:Service> redirect1 bind {port:9090} { @http:ResourceConfig {
methods:["GET"],
path:"/"
}
redirect1 (endpoint client, http:Request req) {
http:Response res = new;
_ = client -> redirect(res, http:REDIRECT_TEMPORARY_REDIRECT_307,
["http://localhost:9093/redirect2"]);
}
}@http:ServiceConfig {
basePath:"/redirect2"
}
service<http:Service> redirect2 bind {port:9093} { @http:ResourceConfig {
methods:["GET"],
path:"/"
}
redirect2 (endpoint client, http:Request req) {
http:Response res = new;
res. setPayload("Hello World!");
_ = client -> respond( res) but { error e => log:printError("Error in
responding", err = e) };
}
}
## http server base path && params
- 参考代码
import ballerina/http;
import ballerina/log;
import ballerina/mime;
@http:ServiceConfig { basePath: "/foo" }
service<http:Service> echo bind { port: 9090 } {
@http:ResourceConfig {
methods: ["POST"],
path: "/bar"
}
echo(endpoint caller, http:Request req) {
var result = req.getJsonPayload();
http:Response res = new;
match result {
error err => {
res.statusCode = 500;
res.setPayload(err.message);
}
json value => {
res.setJsonPayload(value);
}
}
caller->respond(res) but {
error e => log:printError("Error in responding", err = e)
};
}
}
import ballerina/http;
import ballerina/log;@http:ServiceConfig
service<http:Service> sample bind { port: 9090 } { @http:ResourceConfig {
methods: ["GET"],
path: "/path/{foo}"
}
params(endpoint caller, http:Request req, string foo) {
var params = req.getQueryParams();
var bar = <string>params.bar;
map pathMParams = req.getMatrixParams("/sample/path");
var a = <string>pathMParams.a;
var b = <string>pathMParams.b;
string pathMatrixStr = string `a={{a}}, b={{b}}`;
map fooMParams = req.getMatrixParams("/sample/path/" + foo);
var x = <string>fooMParams.x;
var y = <string>fooMParams.y;
string fooMatrixStr = string `x={{x}}, y={{y}}`;
json matrixJson = { "path": pathMatrixStr, "foo": fooMatrixStr };
json responseJson = { "pathParam": foo, "queryParam": bar, "matrix": matrixJson };
http:Response res = new;
res.setJsonPayload(responseJson);
caller->respond(res) but { error e => log:printError("Error when responding", err = e) };
}
}
https server
- 参考代码
import ballerina/http;
import ballerina/log;
endpoint http:Listener helloWorldEP {
port: 9095,
secureSocket: {
keyStore: {
path: "${ballerina.home}/bre/security/ballerinaKeystore.p12",
password: "ballerina"
}
}
};
@http:ServiceConfig {
basePath: "/hello"
}
service helloWorld bind helloWorldEP {
@http:ResourceConfig {
methods: ["GET"],
path: "/"
}
sayHello(endpoint caller, http:Request req) {
http:Response res = new;
res.setPayload("Hello World!");
caller->respond(res) but {
error e => log:printError("Error in responding ", err = e) };
}
}
cors
一般进行跨域处理
- 参考代码
import ballerina/http;
import ballerina/log;
@http:ServiceConfig {
cors: {
allowOrigins: ["http://www.m3.com", "http://www.hello.com"],
allowCredentials: false,
allowHeaders: ["CORELATION_ID"],
exposeHeaders: ["X-CUSTOM-HEADER"],
maxAge: 84900
}
}
service<http:Service> crossOriginService bind { port: 9092 } { string respErr = "Failed to respond to the caller";
@http:ResourceConfig {
methods: ["GET"],
path: "/company",
cors: {
allowOrigins: ["http://www.bbc.com"],
allowCredentials: true,
allowHeaders: ["X-Content-Type-Options", "X-PINGOTHER"]
}
}
companyInfo(endpoint caller, http:Request req) {
http:Response res = new;
json responseJson = { "type": "middleware" };
res.setJsonPayload(responseJson);
caller->respond(res) but { error e => log:printError(respErr, err = e) };
}
@http:ResourceConfig {
methods: ["POST"],
path: "/lang"
}
langInfo(endpoint caller, http:Request req) {
http:Response res = new;
json responseJson = { "lang": "Ballerina" };
res.setJsonPayload(responseJson);
caller->respond(res) but { error e => log:printError(respErr, err = e) };
}
}
数据绑定
http body 序列化
- 参考代码
import ballerina/http;
import ballerina/io;
import ballerina/log;type Student {
string Name;
int Grade;
map Marks;
};
@http:ServiceConfig
service<http:Service> hello bind { port: 9090 } { string respErr = "Failed to respond to the caller";
@http:ResourceConfig {
methods: ["POST"],
body: "orderDetails"
}
bindJson(endpoint caller, http:Request req, json orderDetails) {
json details = orderDetails.Details; http:Response res = new;
res.setPayload(details);
caller->respond(res) but { error e => log:printError(respErr, err = e) };
}
@http:ResourceConfig {
methods: ["POST"],
body: "store",
consumes: ["application/xml"]
}
bindXML(endpoint caller, http:Request req, xml store) {
xml city = store.selectDescendants("{http://www.test.com}city"); http:Response res = new;
res.setPayload(city);
caller->respond(res) but { error e => log:printError(respErr, err = e) };
}
@http:ResourceConfig {
methods: ["POST"],
body: "student",
consumes: ["application/json"]
}
bindStruct(endpoint caller, http:Request req, Student student) {
string name = student.Name; int grade = student.Grade; http:Response res = new;
res.setPayload({ Name: name, Grade: grade });
caller->respond(res) but { error e => log:printError(respErr, err = e) };
}
}
参考资料
https://ballerina.io/learn/by-example/http-client-endpoint.html
https://ballerina.io/learn/by-example/https-listener.html
https://ballerina.io/learn/by-example/http-cors.html
https://ballerina.io/learn/by-example/http-data-binding.html