• 一个简易的SpringCloud Http Post 请求发送工具


           为了方便开发同学,用Python写了一个POST请求发送可执行脚本,方便那些不能使用postman等使用的局域网。当然可以使用CURL命令、用PHP写一个也未尝不可,但并不具备跨平台性。

    当然也可以使用go进行开发。废话不多说,show me code。

    原理:

    获取到 Linux 系统配置的 apollo 配置中心地址:http://apolloUrl/

    通过访问apollo配置中心  http://apolloUrl/configs/公共配置ID/default/公共配置namespace,获取到eureka的服务器地址。

    然后访问 http://eurekaUrl/eureka/apps/ 获取到注册应用的真实ip地址。

    解析XML配置,最后替换并访问正确的目标地址。

    import json
    import os
    import re
    import sys
    
    import requests
    from xml.dom.minidom import parseString
    from sys import argv
    
    # 公共配置appId
    PUBLIC_APOLLO_CONFIG_APP_ID = "xxxx.public"
    # 公共配置namepsace
    PUBLIC_APOLLO_CONFIG_NAMESPACE = "PUBLIC"
    # 公共配置key
    EUREKA_URL_KEY = "eureka.service.url"
    
    JSON_HEADERS = {
        'content-type': "application/json;charset=UTF-8",
        'user-agent': "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36"
    }
    
    
    def doPost(url, postData):
        # 提交post请求
        response = requests.post(url, headers=JSON_HEADERS, data=postData)
        return response
    
    
    def doGet(url):
        # 提交post请求
        response = requests.get(url, headers=JSON_HEADERS)
        return response.text
    
    
    def isIpAddressPort(ipStr):
        p = re.compile('^((25[0-5]|2[0-4]d|[01]?dd?).){3}(25[0-5]|2[0-4]d|[01]?dd?)(:d+)$')
        if p.match(ipStr):
            return True
        else:
            return False
    
    
    def parseEurekaUrl(confgJsonStr):
        data = json.loads(confgJsonStr)
        eurekaUrlStr = data['configurations'][EUREKA_URL_KEY]
        eurekaUrls = eurekaUrlStr.split(',')
        return eurekaUrls[0]
    
    # python解析XML: https://www.cnblogs.com/gide/p/12155821.html
    def getRealIpPort(configXml, appNamStr):
        # 读取文件
        dom = parseString(configXml)
        # 获取文档元素对象
        data = dom.documentElement
        # 获取 student
        applications = data.getElementsByTagName('application')
        for appInfo in applications:
            # 获取标签中内容
            appName = appInfo.getElementsByTagName('name')[0].childNodes[0].nodeValue
            if appName != appNamStr:
                continue
            # 获取标签中内容
            return appInfo.getElementsByTagName('instanceId')[0].childNodes[0].nodeValue
    
    
    def getRealHttpUrl(apolloUrl, httpUrl):
        httpUrlTmp = httpUrl.replace("http://", '')
        httpUrlTmp = httpUrlTmp.replace("https://", '')
        urls = httpUrlTmp.split("/")
        appName = urls[0].upper()
    
        if isIpAddressPort(appName):
            return httpUrl
    
        endStr = apolloUrl[-1]
        if "/" == endStr:
            apolloUrl = apolloUrl[0:-1]
    
        url = apolloUrl + "/configs/" + PUBLIC_APOLLO_CONFIG_APP_ID + "/default/" + PUBLIC_APOLLO_CONFIG_NAMESPACE
        eurekaUrl = parseEurekaUrl(doGet(url))
        endStr = eurekaUrl[-1]
        if "/" == endStr:
            eurekaUrl = eurekaUrl[0:-1]
        eurekaUrl += "/apps"
    
        realIpPort = getRealIpPort(doGet(eurekaUrl), appName)
        return httpUrl.replace(appName, realIpPort)
    
    
    def callService(apolloUrl, httpUrl, postData):
        try:
            httpUrlOrigin = httpUrl
            httpUrl = getRealHttpUrl(apolloUrl=apolloUrl, httpUrl=httpUrl)
    
            print("
    RequestOriginUrl: {}".format(httpUrlOrigin))
            print("RequestMethod: POST")
            print("RequestUrl: {}".format(httpUrl))
            print("RequestData:")
            print("{}".format(json.dumps(json.loads(postData), indent=4)))
            response = json.loads(doPost(httpUrl, postData).text)
            print("ResponseDump:")
            print("{}
    ".format(json.dumps(response, indent=4)))
            print("Response:")
            print("{}
    ".format(json.dumps(response)))
        except Exception as e:
            print("error:{}".format(repr(e)))
    
    
    if __name__ == '__main__':
        apolloUrl = os.getenv('APOLLO_META')
        if 0 == len(apolloUrl):
            print("Please Set the APOLLO_META variable in the /etc/profile file !")
            sys.exit(1)
    
        if len(argv) < 3:
            print("Please input URL and PostData !")
            print(
                "Simple: ./springTest http://ABC/cde/fgh '{"a":"b"}' Or ./springTest http://ip[:port]/cde/fgh '{"a":"b"}'")
            sys.exit(1)
    
        callService(apolloUrl, argv[1], argv[2]) 

    编译成可执行文件:

    pip3 install pyinstaller
    pyinstaller -F springTest.py

    使用示例:

    ./springTest http://应用id/xxxCtl/xxxAction '{"a":"b"}'

    ./springTest http://ip[:port]/xxxCtl/xxxAction '{"a":"b"}'

    Golang版本:

    package main
    
    import (
        "log"
        "fmt"
        "encoding/json"
        "encoding/xml"
        "strings"
        "regexp"
        "bytes"
        "os"
        "net/http"
        "io/ioutil"
    )
    
    //  https://mholt.github.io/json-to-go/
    type PublicConfig struct {
        AppID         string `json:"appId"`
        Cluster       string `json:"cluster"`
        NamespaceName string `json:"namespaceName"`
        Configurations struct {
            ManagementEndpointsWebExposureInclude string `json:"management.endpoints.web.exposure.include"`
            EurekaInstanceInstanceID              string `json:"eureka.instance.instance-id"`
            EurekaClientRegisterWithEureka        string `json:"eureka.client.register-with-eureka"`
            InfoAppName                           string `json:"info.app.name"`
            ManagementEndpointMetricsEnabled      string `json:"management.endpoint.metrics.enabled"`
            EurekaInstanceStatusPageURL           string `json:"eureka.instance.status-page-url"`
            EurekaInstanceMetadataMapAppVersion   string `json:"eureka.instance.metadata-map.app_version"`
            EurekaInstancePreferIPAddress         string `json:"eureka.instance.prefer-ip-address"`
            EurekaClientFetchRegistry             string `json:"eureka.client.fetch-registry"`
            ManagementEndpointHealthShowDetails   string `json:"management.endpoint.health.show-details"`
            EurekaServiceURL                      string `json:"eureka.service.url"`
            EurekaClientServiceURLDefaultZone     string `json:"eureka.client.serviceUrl.defaultZone"`
        } `json:"configurations"`
        ReleaseKey string `json:"releaseKey"`
    }
    
    //  https://www.onlinetool.io/xmltogo/
    type SpringApplicationConfig struct {
        XMLName       xml.Name `xml:"applications"`
        VersionsDelta string   `xml:"versions__delta"`
        AppsHashcode  string   `xml:"apps__hashcode"`
        Application []struct {
            Name string `xml:"name"`
            Instance struct {
                InstanceId       string `xml:"instanceId"`
                HostName         string `xml:"hostName"`
                App              string `xml:"app"`
                IpAddr           string `xml:"ipAddr"`
                Status           string `xml:"status"`
                Overriddenstatus string `xml:"overriddenstatus"`
                Port struct {
                    Text    string `xml:",chardata"`
                    Enabled string `xml:"enabled,attr"`
                } `xml:"port"`
                SecurePort struct {
                    Text    string `xml:",chardata"`
                    Enabled string `xml:"enabled,attr"`
                } `xml:"securePort"`
                CountryId string `xml:"countryId"`
                DataCenterInfo struct {
                    Text  string `xml:",chardata"`
                    Class string `xml:"class,attr"`
                    Name  string `xml:"name"`
                } `xml:"dataCenterInfo"`
                LeaseInfo struct {
                    Text                  string `xml:",chardata"`
                    RenewalIntervalInSecs string `xml:"renewalIntervalInSecs"`
                    DurationInSecs        string `xml:"durationInSecs"`
                    RegistrationTimestamp string `xml:"registrationTimestamp"`
                    LastRenewalTimestamp  string `xml:"lastRenewalTimestamp"`
                    EvictionTimestamp     string `xml:"evictionTimestamp"`
                    ServiceUpTimestamp    string `xml:"serviceUpTimestamp"`
                } `xml:"leaseInfo"`
                Metadata struct {
                    Text           string `xml:",chardata"`
                    Class          string `xml:"class,attr"`
                    ManagementPort string `xml:"management.port"`
                    InstanceId     string `xml:"instanceId"`
                } `xml:"metadata"`
                HomePageUrl                   string `xml:"homePageUrl"`
                StatusPageUrl                 string `xml:"statusPageUrl"`
                HealthCheckUrl                string `xml:"healthCheckUrl"`
                VipAddress                    string `xml:"vipAddress"`
                SecureVipAddress              string `xml:"secureVipAddress"`
                IsCoordinatingDiscoveryServer string `xml:"isCoordinatingDiscoveryServer"`
                LastUpdatedTimestamp          string `xml:"lastUpdatedTimestamp"`
                LastDirtyTimestamp            string `xml:"lastDirtyTimestamp"`
                ActionType                    string `xml:"actionType"`
                AppGroupName                  string `xml:"appGroupName"`
            } `xml:"instance"`
        } `xml:"application"`
    }
    
    // 公共配置appId
    const PUBLIC_APOLLO_CONFIG_APP_ID = "xxxx.public"
    
    // 公共配置namepsace
    const PUBLIC_APOLLO_CONFIG_NAMESPACE = "PUBLIC"
    
    // 公共配置key
    const EUREKA_URL_KEY = "eureka.service.url"
    
    func doPost(url string, postData string) string {
        client := &http.Client{}
        reqBytes := bytes.NewBuffer([]byte(postData))
        request, _ := http.NewRequest("POST", url, reqBytes)
        request.Header.Set("Connection", "keep-alive")
        request.Header.Set("Content-type", "application/json;charset=UTF-8")
        request.Header.Set("user-agent", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36")
        response, _ := client.Do(request)
        if response.StatusCode != 200 {
            return ""
        }
    
        body, _ := ioutil.ReadAll(response.Body)
        return string(body);
    }
    
    func doGet(url string) string {
        // 提交get请求
        client := &http.Client{}
        request, _ := http.NewRequest("GET", url, nil)
        request.Header.Set("Connection", "keep-alive")
        response, _ := client.Do(request)
        if response.StatusCode != 200 {
            return ""
        }
    
        body, _ := ioutil.ReadAll(response.Body)
        return string(body);
    }
    
    func parseEurekaUrl(apolloUrl string) string {
        data := doGet(apolloUrl)
    
        config := PublicConfig{}
    
        err := json.Unmarshal([]byte(data), &config)
        //解析失败会报错,如json字符串格式不对,缺"号,缺}等。
        if err != nil {
            fmt.Println(err)
        }
        eurekaUrlStr := config.Configurations.EurekaServiceURL;
        eurekaUrls := strings.Split(eurekaUrlStr, ",");
        eurekaUrl := eurekaUrls[0]
    
        endStr := eurekaUrl[len(eurekaUrl)-1:]
        if "/" == endStr {
            eurekaUrl = eurekaUrl[0 : len(eurekaUrl)-1]
        }
        return eurekaUrl + "/apps";
    }
    
    func jsonStr2Map(jsonStr string) map[string]interface{} {
        var mapResult map[string]interface{}
        //使用 json.Unmarshal(data []byte, v interface{})进行转换,返回 error 信息
        if err := json.Unmarshal([]byte(jsonStr), &mapResult); err != nil {
            log.Fatal(err)
            return nil
        }
    
        return mapResult
    }
    
    func dumJsonStr(jsonStr string) {
        var out bytes.Buffer
        err := json.Indent(&out, []byte(jsonStr), "", "	")
    
        if err != nil {
            log.Fatalln(err)
        }
    
        out.WriteTo(os.Stdout)
    }
    
    func getRealIpPort(eurekaUrl string, appNamStr string) string {
        dataXml := doGet(eurekaUrl)
        springAppConfig := SpringApplicationConfig{}
        err := xml.Unmarshal([]byte(dataXml), &springAppConfig)
        if err != nil {
            fmt.Printf("error: %v", err)
            return ""
        }
    
        applications := springAppConfig.Application;
        var realIpPort = ""
        for _, value := range applications {
            if appNamStr == value.Name {
                realIpPort = value.Instance.InstanceId;
                break;
            }
        }
    
        return realIpPort
    }
    
    func getRealHttpUrl(apolloUrl string, httpUrl string) string {
        httpUrlTmp := strings.Replace(httpUrl, "http://", "", -1)
        httpUrlTmp = strings.Replace(httpUrlTmp, "https://", "", -1)
        urls := strings.Split(httpUrlTmp, "/")
        appName := strings.ToUpper(urls[0])
    
        if isIpAddressPort(appName) {
            return httpUrl
        }
    
        endStr := apolloUrl[len(apolloUrl)-1:]
        if "/" == endStr {
            apolloUrl = apolloUrl[0 : len(apolloUrl)-1]
        }
    
        url := apolloUrl + "/configs/" + PUBLIC_APOLLO_CONFIG_APP_ID + "/default/" + PUBLIC_APOLLO_CONFIG_NAMESPACE
    
        eurekaUrl := parseEurekaUrl(url)
        realIpPort := getRealIpPort(eurekaUrl, appName)
        return strings.Replace(httpUrl, appName, realIpPort, -1)
    }
    
    func isIpAddressPort(ipStr string) bool {
        if isOk, _ := regexp.MatchString(`^((25[0-5]|2[0-4]d|[01]?dd?).){3}(25[0-5]|2[0-4]d|[01]?dd?)(:d+)$`, ipStr); isOk {
            return isOk
        }
        return false
    }
    
    func callService(apolloUrl string, httpUrl string, postData string) {
        httpUrlOrigin := httpUrl
        httpUrl = getRealHttpUrl(apolloUrl, httpUrl)
        fmt.Println("
    RequestOriginUrl: " + httpUrlOrigin)
        fmt.Println("RequestMethod: POST")
        fmt.Println("RequestUrl: " + httpUrl)
        fmt.Println("RequestData:" + postData)
        response := doPost(httpUrl, postData)
        fmt.Println("
    ResponseDump:")
        dumJsonStr(response)
        fmt.Println("
    ")
        fmt.Println("Response:")
        fmt.Println(response)
        fmt.Println("
    ")
    }
    
    func main() {
        apolloUrl := os.Getenv("APOLLO_META")
        if 0 == len(apolloUrl) {
            fmt.Println("Please Set the APOLLO_META variable in the /etc/profile file !")
            os.Exit(1)
        }
    
        if len(os.Args) < 3 {
            fmt.Println("Simple: ./springTest http://ABC/cde/fgh '{"a":"b"}' Or ./springTest http://ip[:port]/cde/fgh '{"a":"b"}'")
            os.Exit(1)
        }
    
        callService(apolloUrl, os.Args[1], os.Args[2])
    }

    编译:

    go build springTest.go

    在当前目录下会生成一个springTest可执行文件。

    Shell简易版本,不支持SpringCloud:

    #!/bin/bash
    
    URL=$1
    DATA_JSON=$2
    
    if [ "${URL}"x == ""x ];then
        echo "第一个参数为URL,第二个参数为json字符串";
        echo "例如: ./[self].sh http://www.baidu.com '{"a":"b"}'"
        exit 0
    fi
    
    if [ "${DATA_JSON}"x == ""x ];then
        echo "第二个参数为json字符串不能为空";
        exit 0
    fi
    
    
    CURL_CMD="curl -H "Content-Type:application/json" -X POST --data '${DATA_JSON}' ${URL}"
    
    echo ""
    echo "${CURL_CMD}"
    echo "========================================================================================="
    echo ""
    eval ${CURL_CMD}
    echo ""
    echo ""

    PS:

    编译时报依赖库不存在解决办法:http://www.pythonheidong.com/blog/article/158136/

  • 相关阅读:
    LINQ查询表达式(5)
    LINQ查询表达式(4)
    并不对劲的loj2279
    并不对劲的bzoj1563:p1912:[NOI2009]诗人小G
    并不对劲的loj507
    并不对劲的loj2332
    并不对劲的loj6191
    并不对劲的bzoj4552:p2824:[HEOI2016/TJOI2016]排序
    并不对劲的bzoj3924:loj2135:p3345:[ZJOI2015]幻想乡战略游戏
    并不对劲的bzoj3295:[CQOI2011]动态逆序对
  • 原文地址:https://www.cnblogs.com/phpdragon/p/12551992.html
Copyright © 2020-2023  润新知