289 lines
6.8 KiB
Go
289 lines
6.8 KiB
Go
|
package main
|
||
|
|
||
|
import (
|
||
|
"flag"
|
||
|
"fmt"
|
||
|
"html"
|
||
|
"io"
|
||
|
"log"
|
||
|
"net/http"
|
||
|
"os"
|
||
|
"sort"
|
||
|
"strings"
|
||
|
"time"
|
||
|
|
||
|
re2 "github.com/dlclark/regexp2"
|
||
|
ini "gopkg.in/ini.v1"
|
||
|
)
|
||
|
|
||
|
var ver string = "2.0.3"
|
||
|
var vsn bool = false
|
||
|
var cfg *ini.File
|
||
|
|
||
|
var (
|
||
|
uri string
|
||
|
server string
|
||
|
port string
|
||
|
plantCode string
|
||
|
funcName string
|
||
|
input string
|
||
|
output string
|
||
|
timeout int
|
||
|
debug bool = false
|
||
|
)
|
||
|
|
||
|
func init() {
|
||
|
flag.BoolVar(&vsn, "v", false, "Show Program Version")
|
||
|
flag.BoolVar(&debug, "d", false, "Show Debug Messages")
|
||
|
flag.IntVar(&timeout, "t", 10, "Timeout in Seconds")
|
||
|
flag.StringVar(&server, "s", "127.0.0.1", "Web Service Server")
|
||
|
flag.StringVar(&port, "p", "80", "Web Service Listen Port")
|
||
|
flag.StringVar(&plantCode, "x", "", "PlantCode Suffix in Web Service URL")
|
||
|
flag.StringVar(&funcName, "f", "", "Function Name")
|
||
|
flag.StringVar(&input, "i", "./TesterWebSvc.ini", "Input Filename")
|
||
|
flag.StringVar(&output, "o", "./TesterWebSvcResult.ini", "Output Filename")
|
||
|
flag.Parse()
|
||
|
}
|
||
|
|
||
|
func main() {
|
||
|
log.SetFlags(log.Ldate | log.Ltime | log.Lmicroseconds)
|
||
|
log.SetOutput(os.Stdout)
|
||
|
|
||
|
if vsn {
|
||
|
fmt.Printf("%s, Version: %s\r\n", os.Args[0], ver)
|
||
|
os.Exit(0)
|
||
|
}
|
||
|
|
||
|
if funcName == "" {
|
||
|
log.Println("[ERR] Missing Function Name.")
|
||
|
os.Exit(1)
|
||
|
}
|
||
|
|
||
|
if input == "" || output == "" {
|
||
|
log.Println("[ERR] Missing Input and/or Output Filename.")
|
||
|
os.Exit(1)
|
||
|
}
|
||
|
|
||
|
if plantCode != "" {
|
||
|
plantCode = "." + plantCode
|
||
|
}
|
||
|
uri = fmt.Sprintf("http://%s:%s/Tester.WebService%s/WebService.asmx", server, port, plantCode)
|
||
|
|
||
|
var err error
|
||
|
cfg, err = ini.Load(input)
|
||
|
if err != nil {
|
||
|
log.Printf("[ERR] %v\r\n", err)
|
||
|
os.Exit(1)
|
||
|
}
|
||
|
|
||
|
keys := cfg.Section("SFC").KeyStrings()
|
||
|
if len(keys) == 0 {
|
||
|
log.Printf("[ERR] Invalid Config: %s\r\n", input)
|
||
|
os.Exit(1)
|
||
|
}
|
||
|
|
||
|
args := make(map[string]string, 0)
|
||
|
for _, k := range keys {
|
||
|
v := cfg.Section("SFC").Key(k).MustString("")
|
||
|
args[k] = strings.TrimSpace(v)
|
||
|
}
|
||
|
|
||
|
if debug {
|
||
|
log.Printf("[MSG] WebSvcUrl:\t%s\r\n", uri)
|
||
|
log.Printf("[MSG] Function:\t%s\r\n", funcName)
|
||
|
log.Printf("[MSG] Arguments:\t%#v\r\n", args)
|
||
|
}
|
||
|
|
||
|
argStr := ""
|
||
|
for k, v := range args {
|
||
|
argStr = argStr + "<" + k + ">" + v + "</" + k + ">"
|
||
|
}
|
||
|
if funcName == "Complete" {
|
||
|
argStr = argStr + fmt.Sprintf("<TrnDatas><TrnData>%s</TrnData></TrnDatas>", args["UnitSerialNumber"])
|
||
|
}
|
||
|
|
||
|
result, err := _TesterWebService(funcName, argStr)
|
||
|
if err != nil {
|
||
|
log.Printf("[ERR] %#v\r\n", err)
|
||
|
os.Exit(1)
|
||
|
}
|
||
|
|
||
|
if debug {
|
||
|
log.Printf("[MSG] Result:\t%#v\r\n", result)
|
||
|
}
|
||
|
|
||
|
// 对结果集按Map的Key名称排序
|
||
|
resultKeys := make([]string, 0, len(result))
|
||
|
for k := range result {
|
||
|
resultKeys = append(resultKeys, k)
|
||
|
}
|
||
|
sort.Strings(resultKeys)
|
||
|
|
||
|
// 将排序后的结果集写入 Output File
|
||
|
content := fmt.Sprintf("[%s]\r\n", "SFC")
|
||
|
for _, rk := range resultKeys {
|
||
|
content = content + rk + "=" + result[rk] + "\r\n"
|
||
|
}
|
||
|
|
||
|
fo, err := os.OpenFile(output, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
|
||
|
if err != nil {
|
||
|
log.Printf("[ERR] %v\r\n", err)
|
||
|
os.Exit(1)
|
||
|
}
|
||
|
defer fo.Close()
|
||
|
|
||
|
_, err = fo.WriteString(content)
|
||
|
if err != nil {
|
||
|
log.Printf("[ERR] %v\r\n", err)
|
||
|
os.Exit(1)
|
||
|
}
|
||
|
fo.Sync()
|
||
|
}
|
||
|
|
||
|
func _TesterWebService(funcName string, argStr string) (map[string]string, error) {
|
||
|
result := make(map[string]string, 0)
|
||
|
|
||
|
xmlXSI := `"http://www.w3.org/2001/XMLSchema-instance"`
|
||
|
xmlXSD := `"http://www.w3.org/2001/XMLSchema"`
|
||
|
xmlSCH := `"http://schemas.xmlsoap.org/soap/envelope/"`
|
||
|
|
||
|
reqStr := fmt.Sprintf(`<?xml version="1.0" encoding="utf-8"?>
|
||
|
<soap:Envelope xmlns:xsi=%s xmlns:xsd=%s xmlns:soap=%s>
|
||
|
<soap:Body>
|
||
|
<%s xmlns="http://localhost/Tester.WebService/WebService">
|
||
|
%s
|
||
|
</%s>
|
||
|
</soap:Body>
|
||
|
</soap:Envelope>`,
|
||
|
xmlXSI, xmlXSD, xmlSCH, funcName, argStr, funcName)
|
||
|
|
||
|
client := http.Client{
|
||
|
Timeout: time.Second * time.Duration(timeout),
|
||
|
}
|
||
|
req, err := http.NewRequest("POST", uri, strings.NewReader(reqStr))
|
||
|
if err != nil {
|
||
|
return result, err
|
||
|
}
|
||
|
defer req.Body.Close()
|
||
|
|
||
|
req.Header.Set("User-Agent", "TesterWebSvcClient-TE")
|
||
|
req.Header.Set("SOAPAction", "http://localhost/Tester.WebService/WebService/"+funcName)
|
||
|
req.Header.Set("Content-Type", "text/xml; charset=utf-8")
|
||
|
res, err := client.Do(req)
|
||
|
if err != nil {
|
||
|
return result, err
|
||
|
}
|
||
|
|
||
|
resByte, err := io.ReadAll(res.Body)
|
||
|
if err != nil {
|
||
|
return result, err
|
||
|
}
|
||
|
resStr := string(resByte)
|
||
|
|
||
|
switch funcName {
|
||
|
case "GetKeyInfoFromView":
|
||
|
result, err = _ParseInfoNameValues(resStr, funcName)
|
||
|
if err != nil {
|
||
|
result["RESULT"] = "NG, ParseInfoNameValues: " + err.Error()
|
||
|
return result, err
|
||
|
}
|
||
|
default:
|
||
|
result, err = _ParseWebServiceResult(resStr, funcName)
|
||
|
if err != nil {
|
||
|
result["RESULT"] = "NG, ParseWebServiceResult: " + err.Error()
|
||
|
return result, err
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if len(result) == 0 {
|
||
|
result["RESULT"] = fmt.Sprintf("NG, %s: Empty Response.", funcName)
|
||
|
}
|
||
|
|
||
|
return result, nil
|
||
|
}
|
||
|
|
||
|
// Parse SFCS Web Service Result
|
||
|
func _ParseWebServiceResult(src, fnc string) (map[string]string, error) {
|
||
|
ret := make(map[string]string, 0)
|
||
|
reg, err := re2.Compile(`<(\S{1,})( xmlns=.*){0,1}>([^<>]{1,})</\1>`, 0)
|
||
|
if err != nil {
|
||
|
ret["RESULT"] = "NG"
|
||
|
ret["ErrMsg"] = err.Error()
|
||
|
return ret, err
|
||
|
}
|
||
|
tch, err := reg.FindStringMatch(src)
|
||
|
if err != nil {
|
||
|
ret["RESULT"] = "NG"
|
||
|
ret["ErrMsg"] = err.Error()
|
||
|
return ret, err
|
||
|
}
|
||
|
for tch != nil {
|
||
|
grp := tch.Groups()
|
||
|
if len(grp) == 4 {
|
||
|
tag := html.UnescapeString(grp[1].String())
|
||
|
txt := html.UnescapeString(grp[3].String())
|
||
|
if tag == fnc+"Result" || tag == "Result" || tag == "result" || tag == "faultstring" {
|
||
|
tag = "RESULT"
|
||
|
}
|
||
|
ret[tag] = txt
|
||
|
}
|
||
|
tch, _ = reg.FindNextMatch(tch)
|
||
|
}
|
||
|
return ret, nil
|
||
|
}
|
||
|
|
||
|
// Parse SFCS Web Service Result - InfoName Pairs
|
||
|
func _ParseInfoNameValues(src, fnc string) (map[string]string, error) {
|
||
|
ret := make(map[string]string, 0)
|
||
|
reg, err := re2.Compile(`<([^:]{1,})>([^<>]{1,})</\1>`, 0)
|
||
|
if err != nil {
|
||
|
ret["RESULT"] = "NG"
|
||
|
ret["ErrMsg"] = err.Error()
|
||
|
return ret, err
|
||
|
}
|
||
|
tch, err := reg.FindStringMatch(src)
|
||
|
if err != nil {
|
||
|
ret["RESULT"] = "NG"
|
||
|
ret["ErrMsg"] = err.Error()
|
||
|
return ret, err
|
||
|
}
|
||
|
for tch != nil {
|
||
|
grp := tch.Groups()
|
||
|
if len(grp) == 3 {
|
||
|
tag := grp[1].String()
|
||
|
txt := grp[2].String()
|
||
|
if tag == fnc+"Result" || tag == "Result" || tag == "result" || tag == "faultstring" {
|
||
|
tag = "RESULT"
|
||
|
ret[tag] = txt
|
||
|
}
|
||
|
}
|
||
|
tch, _ = reg.FindNextMatch(tch)
|
||
|
}
|
||
|
|
||
|
// Parse Info Name/Values Sets
|
||
|
regNV, err := re2.Compile(`<InfoName>([^<>]{1,})</InfoName>\s*<InfoValue>([^<>]{1,})</InfoValue>`, 0)
|
||
|
if err != nil {
|
||
|
ret["RESULT"] = "NG"
|
||
|
ret["ErrMsg"] = err.Error()
|
||
|
return ret, err
|
||
|
}
|
||
|
tchNV, err := regNV.FindStringMatch(src)
|
||
|
if err != nil {
|
||
|
ret["RESULT"] = "NG"
|
||
|
ret["ErrMsg"] = err.Error()
|
||
|
return ret, err
|
||
|
}
|
||
|
for tchNV != nil {
|
||
|
grp := tchNV.Groups()
|
||
|
if len(grp) == 3 {
|
||
|
name := html.UnescapeString(grp[1].String())
|
||
|
value := html.UnescapeString(grp[2].String())
|
||
|
if strings.TrimSpace(name) != "" {
|
||
|
ret[name] = value
|
||
|
}
|
||
|
}
|
||
|
tchNV, _ = regNV.FindNextMatch(tchNV)
|
||
|
}
|
||
|
return ret, nil
|
||
|
}
|