Skip to content

Commit 213e6ed

Browse files
committed
git commit -m "clientapi: prepare 2.0.0 — refactor & decouple (Aphrodite → Shamash).Signed-off-by: Ahmad <ahmad.alsanie@hotmail.com>"
1 parent dfad553 commit 213e6ed

10 files changed

Lines changed: 757 additions & 811 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1212
- Keep ClientApi as transport + gen API owner
1313
- Simplify CLI orchestration (ClientApiMain)
1414
- Disable japicmp for initial 2.x release
15+
- Introduced internal workflows and services
16+
- No functional changes intended
1517

1618
### Removed
1719
- Removed `JDOM` dependency

‎subprojects/zap-clientapi/src/main/java/org/zaproxy/clientapi/core/ClientApi.java‎

Lines changed: 123 additions & 560 deletions
Large diffs are not rendered by default.

‎subprojects/zap-clientapi/src/main/java/org/zaproxy/clientapi/core/ClientApiMain.java‎

Lines changed: 65 additions & 251 deletions
Large diffs are not rendered by default.
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/*
2+
* Zed Attack Proxy (ZAP) and its related class files.
3+
*
4+
* ZAP is an HTTP/HTTPS proxy for assessing web application security.
5+
*
6+
* Copyright 2025 The ZAP Development Team
7+
*
8+
* Licensed under the Apache License, Version 2.0 (the "License");
9+
* you may not use this file except in compliance with the License.
10+
* You may obtain a copy of the License at
11+
*
12+
* http://www.apache.org/licenses/LICENSE-2.0
13+
*
14+
* Unless required by applicable law or agreed to in writing, software
15+
* distributed under the License is distributed on an "AS IS" BASIS,
16+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17+
* See the License for the specific language governing permissions and
18+
* limitations under the License.
19+
*/
20+
package org.zaproxy.clientapi.core;
21+
22+
/*
23+
* Zed Attack Proxy (ZAP) and its related class files.
24+
*
25+
* Licensed under the Apache License, Version 2.0
26+
*/
27+
28+
import java.net.URL;
29+
import java.util.Collections;
30+
import java.util.HashMap;
31+
import java.util.Map;
32+
33+
/**
34+
* A simple immutable HTTP request representation used internally by the Client API.
35+
*
36+
* <p>This class intentionally contains no networking logic.
37+
*/
38+
public final class HttpRequest {
39+
40+
public static final String GET_METHOD = "GET";
41+
42+
private final String method;
43+
private final URL requestUri;
44+
private final Map<String, String> headers;
45+
private final String body;
46+
47+
public HttpRequest(String method, URL requestUri, String body) {
48+
this.method = method;
49+
this.requestUri = requestUri;
50+
this.body = body;
51+
this.headers = new HashMap<>();
52+
}
53+
54+
public String getMethod() {
55+
return method;
56+
}
57+
58+
public URL getRequestUri() {
59+
return requestUri;
60+
}
61+
62+
public String getBody() {
63+
return body;
64+
}
65+
66+
/**
67+
* Adds or replaces a request header.
68+
*
69+
* @param name header name
70+
* @param value header value
71+
*/
72+
public void addHeader(String name, String value) {
73+
headers.put(name, value);
74+
}
75+
76+
/**
77+
* Returns an unmodifiable view of the request headers.
78+
*
79+
* @return headers map
80+
*/
81+
public Map<String, String> getHeaders() {
82+
return Collections.unmodifiableMap(headers);
83+
}
84+
}
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
/*
2+
* Zed Attack Proxy (ZAP) and its related class files.
3+
*
4+
* ZAP is an HTTP/HTTPS proxy for assessing web application security.
5+
*
6+
* Copyright 2025 The ZAP Development Team
7+
*
8+
* Licensed under the Apache License, Version 2.0 (the "License");
9+
* you may not use this file except in compliance with the License.
10+
* You may obtain a copy of the License at
11+
*
12+
* http://www.apache.org/licenses/LICENSE-2.0
13+
*
14+
* Unless required by applicable law or agreed to in writing, software
15+
* distributed under the License is distributed on an "AS IS" BASIS,
16+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17+
* See the License for the specific language governing permissions and
18+
* limitations under the License.
19+
*/
20+
package org.zaproxy.clientapi.core;
21+
22+
/*
23+
* Zed Attack Proxy (ZAP) and its related class files.
24+
*
25+
* ZAP is an HTTP/HTTPS proxy for assessing web application security.
26+
*
27+
* Copyright 2011 The ZAP Development Team
28+
*
29+
* Licensed under the Apache License, Version 2.0 (the "License");
30+
* you may not use this file except in compliance with the License.
31+
* You may obtain a copy of the License at
32+
*
33+
* http://www.apache.org/licenses/LICENSE-2.0
34+
*
35+
* Unless required by applicable law or agreed to in writing, software
36+
* distributed under the License is distributed on an "AS IS" BASIS,
37+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
38+
* See the License for the specific language governing permissions and
39+
* limitations under the License.
40+
*/
41+
42+
import java.net.MalformedURLException;
43+
import java.net.URI;
44+
import java.net.URISyntaxException;
45+
import java.net.URL;
46+
import java.net.URLEncoder;
47+
import java.nio.charset.StandardCharsets;
48+
import java.util.Map;
49+
50+
/**
51+
* Builds HTTP requests for the ZAP API.
52+
*
53+
* <p>This class is responsible only for request construction (URL, query parameters, body,
54+
* headers).
55+
*
56+
* <p>No networking or I/O is performed here.
57+
*/
58+
final class ZapRequestBuilder {
59+
60+
private static final String ZAP_API_HOST = "http://zap/";
61+
62+
private ZapRequestBuilder() {
63+
// utility class
64+
}
65+
66+
static HttpRequest buildZapRequest(
67+
String requestMethod,
68+
String format,
69+
String component,
70+
String type,
71+
String method,
72+
Map<String, String> params,
73+
String apiKey)
74+
throws MalformedURLException, URISyntaxException {
75+
76+
StringBuilder urlBuilder = new StringBuilder();
77+
urlBuilder
78+
.append(ZAP_API_HOST)
79+
.append(format)
80+
.append('/')
81+
.append(component)
82+
.append('/')
83+
.append(type)
84+
.append('/')
85+
.append(method)
86+
.append('/');
87+
88+
String body = null;
89+
90+
if (params != null && !params.isEmpty()) {
91+
if (HttpRequest.GET_METHOD.equals(requestMethod)) {
92+
urlBuilder.append('?');
93+
appendParams(params, urlBuilder);
94+
} else {
95+
body = appendParams(params, new StringBuilder()).toString();
96+
}
97+
}
98+
99+
HttpRequest request =
100+
new HttpRequest(requestMethod, createUrl(urlBuilder.toString()), body);
101+
102+
if (apiKey != null && !apiKey.isEmpty()) {
103+
request.addHeader("X-ZAP-API-Key", apiKey);
104+
}
105+
106+
return request;
107+
}
108+
109+
private static URL createUrl(String value) throws MalformedURLException, URISyntaxException {
110+
return new URI(value).toURL();
111+
}
112+
113+
private static StringBuilder appendParams(Map<String, String> params, StringBuilder sb) {
114+
115+
for (Map.Entry<String, String> p : params.entrySet()) {
116+
sb.append(encode(p.getKey())).append('=');
117+
if (p.getValue() != null) {
118+
sb.append(encode(p.getValue()));
119+
}
120+
sb.append('&');
121+
}
122+
return sb;
123+
}
124+
125+
private static String encode(String value) {
126+
return URLEncoder.encode(value, StandardCharsets.UTF_8);
127+
}
128+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
* Zed Attack Proxy (ZAP) and its related class files.
3+
*
4+
* ZAP is an HTTP/HTTPS proxy for assessing web application security.
5+
*
6+
* Copyright 2025 The ZAP Development Team
7+
*
8+
* Licensed under the Apache License, Version 2.0 (the "License");
9+
* you may not use this file except in compliance with the License.
10+
* You may obtain a copy of the License at
11+
*
12+
* http://www.apache.org/licenses/LICENSE-2.0
13+
*
14+
* Unless required by applicable law or agreed to in writing, software
15+
* distributed under the License is distributed on an "AS IS" BASIS,
16+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17+
* See the License for the specific language governing permissions and
18+
* limitations under the License.
19+
*/
20+
package org.zaproxy.clientapi.internal;
21+
22+
import java.io.File;
23+
import java.util.List;
24+
import java.util.Map;
25+
import org.zaproxy.clientapi.core.Alert;
26+
import org.zaproxy.clientapi.core.AlertsFile;
27+
import org.zaproxy.clientapi.core.ClientApi;
28+
import org.zaproxy.clientapi.core.ClientApiException;
29+
import org.zaproxy.clientapi.service.AlertService;
30+
31+
public final class AlertWorkflow {
32+
33+
private AlertWorkflow() {
34+
// utility class
35+
}
36+
37+
public static void checkAlerts(
38+
ClientApi api,
39+
AlertService alertService,
40+
List<Alert> ignoreAlerts,
41+
List<Alert> requireAlerts)
42+
throws ClientApiException {
43+
44+
Map<String, List<Alert>> results =
45+
alertService.checkAlerts(ignoreAlerts, requireAlerts, api.alert);
46+
47+
alertService.verifyAlerts(results.get("requireAlerts"), results.get("reportAlerts"));
48+
}
49+
50+
public static void checkAlerts(
51+
ClientApi api,
52+
AlertService alertService,
53+
List<Alert> ignoreAlerts,
54+
List<Alert> requireAlerts,
55+
File outputFile)
56+
throws ClientApiException {
57+
58+
Map<String, List<Alert>> results =
59+
alertService.checkAlerts(ignoreAlerts, requireAlerts, api.alert);
60+
61+
try {
62+
AlertsFile.saveAlertsToFile(
63+
results.get("requireAlerts"),
64+
results.get("reportAlerts"),
65+
results.get("ignoredAlerts"),
66+
outputFile);
67+
} catch (Exception e) {
68+
throw new ClientApiException("Failed to save the alerts.", e);
69+
}
70+
71+
int alertsFound = results.get("reportAlerts").size();
72+
int alertsMissing = results.get("requireAlerts").size();
73+
74+
if (alertsFound > 0 || alertsMissing > 0) {
75+
throw new ClientApiException(
76+
"Check Alerts Failed! Found=" + alertsFound + ", Missing=" + alertsMissing);
77+
}
78+
}
79+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*
2+
* Zed Attack Proxy (ZAP) and its related class files.
3+
*
4+
* ZAP is an HTTP/HTTPS proxy for assessing web application security.
5+
*
6+
* Copyright 2025 The ZAP Development Team
7+
*
8+
* Licensed under the Apache License, Version 2.0 (the "License");
9+
* you may not use this file except in compliance with the License.
10+
* You may obtain a copy of the License at
11+
*
12+
* http://www.apache.org/licenses/LICENSE-2.0
13+
*
14+
* Unless required by applicable law or agreed to in writing, software
15+
* distributed under the License is distributed on an "AS IS" BASIS,
16+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17+
* See the License for the specific language governing permissions and
18+
* limitations under the License.
19+
*/
20+
package org.zaproxy.clientapi.internal;
21+
22+
import java.net.URL;
23+
import java.util.ArrayList;
24+
import java.util.List;
25+
import org.zaproxy.clientapi.core.ApiResponse;
26+
import org.zaproxy.clientapi.core.ApiResponseElement;
27+
import org.zaproxy.clientapi.core.ApiResponseList;
28+
import org.zaproxy.clientapi.core.ClientApi;
29+
30+
public final class ContextWorkflow {
31+
32+
private ContextWorkflow() {
33+
// utility class
34+
}
35+
36+
public static void includeOneMatchingNode(ClientApi api, String contextName, String regex)
37+
throws Exception {
38+
39+
List<String> sessionUrls = getSessionUrls(api);
40+
boolean foundOne = false;
41+
42+
for (String sessionUrl : sessionUrls) {
43+
if (sessionUrl.matches(regex)) {
44+
if (foundOne) {
45+
api.context.excludeFromContext(contextName, regex);
46+
} else {
47+
foundOne = true;
48+
}
49+
}
50+
}
51+
52+
if (!foundOne) {
53+
throw new Exception("Unexpected result: No url found matching regex " + regex);
54+
}
55+
}
56+
57+
private static List<String> getSessionUrls(ClientApi api) throws Exception {
58+
List<String> urls = new ArrayList<>();
59+
ApiResponse response = api.core.urls();
60+
61+
if (response instanceof ApiResponseList) {
62+
for (ApiResponse element : ((ApiResponseList) response).getItems()) {
63+
64+
String value = ((ApiResponseElement) element).getValue();
65+
URL url = new URL(value);
66+
urls.add(url.getProtocol() + "://" + url.getHost() + url.getPath());
67+
}
68+
}
69+
return urls;
70+
}
71+
}

0 commit comments

Comments
 (0)