-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSOAP_client.ts
124 lines (113 loc) · 4.95 KB
/
SOAP_client.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import { default as fetch }from 'node-fetch';
import { createEnvelopeMessage, extractLogs, getResponseCode, MultipartMessage, ServerAction } from './mime';
import { ServerResult } from './server_result';
import { log } from '../logger';
/*
1. Gather all the information for the message from the text (start with hardcoded)
3. Create the message
4. Figure out address, port etc and send message
5. Parse response to get ID
6. Poll server (GET at /p/<responseID>) until done
7. Send "response" message to server
8. Unpack response to get validation results
*/
export class SOAPClient {
url: string = "http://build-oracc.museum.upenn.edu";
port: number = 8085;
atf_filename: string;
atf_text: string;
atf_project: string;
responseID: string;
constructor(atf_name: string, atf_project: string, atf_text: string) {
this.atf_text = atf_text;
this.atf_filename = atf_name;
this.atf_project = atf_project;
this.atf_text = atf_text;
}
async executeCommand(command: ServerAction): Promise<ServerResult> {
try {
this.responseID = await this.sendInitialRequest(command);
log('debug', `Got response code ${this.responseID}`);
await this.serverComplete();
log('debug', `Request ${this.responseID} is done.`);
const finalResult = await this.retrieveReponse();
// If it exists, the name of the lemmatised file will have the form
// <filename without .atf extension>-autolem.atf
const lemmatisedName = `${this.atf_filename.slice(0, -4)}-autolem.atf`
return new ServerResult(finalResult.get('oracc.log'),
finalResult.get('request.log'),
finalResult.get(lemmatisedName));
} catch (err) {
throw `Error during communication with server: ${err}`;
}
}
async sendInitialRequest(command): Promise<string> {
const fullMessage = new MultipartMessage(command, this.atf_filename,
this.atf_project, this.atf_text);
log('debug', fullMessage.toString());
const body = fullMessage.getBody();
const headers = fullMessage.getHeaders();
const options = {
method: 'POST',
headers: headers,
body: body
}
try {
const response = await fetch(`${this.url}:${this.port}`, options);
if (response.status != 200) {
throw `Request failed! Status: ${response.status}`;
}
return getResponseCode(await response.text());
} catch (err) {
log('error', `Problem getting response from server: ${err}`);
throw err;
}
}
async serverComplete(): Promise<void> {
let attempts = 0;
const max_attempts = 10;
while (attempts < max_attempts) {
attempts += 1;
const response = await fetch(`${this.url}/p/${this.responseID}`);
const text = await response.text();
switch (text.trim()) { // Message includes a trailing new line character
case 'done': // done processing
log('debug', `Result ready after ${attempts} attempts.`)
return;
case 'err_stat':
log('error', `Received err_stat for request ${this.responseID}.`);
throw `The server encountered an error while working on the request.
Please contact the Oracc server admin to look into this problem.`;
case 'run':
if (attempts < max_attempts) {
if (attempts == 1) { // Only print once to avoid cluttering log
log('debug', 'Server working on request.');
}
break;
} else {
throw `The Oracc server was unable to elaborate response
for request with id ${this.responseID}. Please contact the
Oracc server admin to look into this problem.`;
}
default:
log('error', `Unexpected message from server: ${text.trim()}`);
throw `Unexpected message from server: ${text.trim()}`;
}
}
}
async retrieveReponse(): Promise<Map<string, string>> {
const message = createEnvelopeMessage({responseID: this.responseID})
.toString({noHeaders: true});
const response = await fetch(
`${this.url}:${this.port}`,
{method: 'POST', body: message}
);
const responseContents = await response.buffer();
const allLogs = extractLogs(responseContents);
allLogs.forEach( (contents, name) => {
log('debug', `${name}`)
log('debug', `${contents}`)
});
return allLogs;
}
}