Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 17 additions & 31 deletions src/main/java/burp/RequestSender.java
Original file line number Diff line number Diff line change
Expand Up @@ -405,42 +405,27 @@ private static URL createNewURLWithSegment(URL orgURL, String additional, String
* Uses Caffeine cache for high-performance caching with TTL.
*/
protected static Map<String, Object> retrieveResponseDetails(IHttpService service, byte[] request) {
return retrieveResponseDetails(service, request, 0);
}

private static Map<String, Object> retrieveResponseDetails(IHttpService service, byte[] request, int retryCount) {
String hostKey = service.getHost();
String cacheKey = service.toString() + Arrays.hashCode(request);
String cacheKey = buildServiceCacheKey(service, request);

for (int attempt = 0; attempt < MAX_RETRIES; attempt++) {
for (int attempt = retryCount; attempt < MAX_RETRIES; attempt++) {
try {
// Check circuit breaker before doing any work
if (isCircuitOpen(hostKey)) {
BurpExtender.logDebug("Circuit breaker open for " + hostKey);
return null;
}
return retrieveResponseDetails(service, request, 0);
}

private static Map<String, Object> retrieveResponseDetails(IHttpService service, byte[] request, int retryCount) {
try {
String hostKey = service.getHost();
String cacheKey = buildServiceCacheKey(service, request);

// Check circuit breaker
if (isCircuitOpen(hostKey)) {
BurpExtender.logDebug("Circuit breaker open for " + hostKey);
return null;
}

// Rate limiting
if (!checkRateLimit(hostKey)) {
try { Thread.sleep(100); } catch (InterruptedException ignored) {}
}

// Check cache first
Map<String, Object> cached = RESPONSE_CACHE.getIfPresent(cacheKey);
if (cached != null) {
return cached;
}

waitForRateLimit(hostKey);
// Respect host-level rate limiting
if (!checkRateLimit(hostKey)) {
waitForRateLimit(hostKey);
}

// Serve from cache when possible
Map<String, Object> cached = RESPONSE_CACHE.getIfPresent(cacheKey);
if (cached != null) {
return cached;
Expand All @@ -457,9 +442,8 @@ private static Map<String, Object> retrieveResponseDetails(IHttpService service,
recordFailure(hostKey);
if (attempt < MAX_RETRIES - 1) {
sleepRespectingInterrupts(calculateRetryDelay(attempt));
continue;
}
return null;
continue;
}

IResponseInfo responseInfo = BurpExtender.getHelpers().analyzeResponse(response.getResponse());
Expand All @@ -468,8 +452,10 @@ private static Map<String, Object> retrieveResponseDetails(IHttpService service,
details.put("headers", responseInfo.getHeaders());
details.put("responseTime", responseTime);

byte[] responseBody = java.util.Arrays.copyOfRange(response.getResponse(),
responseInfo.getBodyOffset(), response.getResponse().length);
byte[] responseBody = java.util.Arrays.copyOfRange(
response.getResponse(),
responseInfo.getBodyOffset(),
response.getResponse().length);
details.put("body", responseBody);

if (responseInfo.getStatusCode() >= 200 && responseInfo.getStatusCode() < 500) {
Expand Down