Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Monitored requests have no httpBody #203

Closed
fermoya opened this issue Feb 15, 2024 · 20 comments
Closed

Monitored requests have no httpBody #203

fermoya opened this issue Feb 15, 2024 · 20 comments

Comments

@fermoya
Copy link

fermoya commented Feb 15, 2024

Hi, I have this UITest that was previously working in iOS 16.4 simulator. We've moved now to use iOS 17.2 simulator. We're using latest version 10.0.0. I'm monitoring a request and debugging I can see we send a body. However, when I peek the requests:

app.monitoredRequestsPeekAll()

I see my requests have no httpBody somehow whereas if I run the same test on iOS 16.4 I can see the body. This is a regular request using URLSession.dataTask(with:completionHandler).

Any ideas what's wrong?

@tcamin
Copy link
Member

tcamin commented Feb 15, 2024

Hi there! I just tried running the library's test suite on an iOS 17.2 simulator, and tests are passing including a few that also verify the httpBody. Moreover we have several tests in the codebase @Subito that monitor requests and checks the httpBody. Did you try to replicate the issue in a separate project that can be shared? It would make debugging the issue easier.

@magauran
Copy link

Hey @tcamin, I have the same problem.
The issue doesn't seem to reproduce on a small body.

Try to change httpBody in this test to String(repeatElement("a", count: 20000))
and you will see this error in the console:

Dropping oversized protocol property key SBTUITunneledNSURLProtocolHTTPBodyKey in <NSMutableURLRequest: 0x60000000c1e0> { URL: https://httpbin.org/post }

@tcamin
Copy link
Member

tcamin commented Feb 20, 2024

That's interesting! I'll try to take a look as soon as I can.

@tcamin
Copy link
Member

tcamin commented Feb 23, 2024

I've have this open branch to test out hotfix/large_body. I still need to investigate some issues when running in CI but locally it seems to be working. If you try it out let me know!

@fermoya
Copy link
Author

fermoya commented Feb 23, 2024

hey @tcamin thanks for the quick fix. I just tried and whereas now the request has an httpBody it seems that the ObjC casting is off:

Could not cast value of type '__NSCFString' (0x1f1d04258) to 'NSData' (0x1f1d09130).

httpBody is supposed to have NSData type. I've seen this before while working in ObjC

@fermoya
Copy link
Author

fermoya commented Feb 23, 2024

I'm checking the diff:

+ (void)setProperty:(id)property forKey:(nonnull NSString *)key inRequest:(nonnull NSMutableURLRequest *)request
{
    if ([property isKindOfClass:[NSData class]] && ((NSData *)property).length > 16834) { ... }
    else { ... }
}

+ (id)propertyForKey:(NSString *)key inRequest:(NSURLRequest *)request;
{
    id property = [NSURLProtocol propertyForKey:key inRequest:request];
    return [storage objectForKey:property] ?: property;
}

it seems that storage is always storing NSData but propertyForKey returns anything. And there's also a collision of types. If I'm not wrong, [storage objectForKey:property] should return NSData whereas ?: property returns NSString

@fermoya
Copy link
Author

fermoya commented Feb 23, 2024

Yeah so the original body is something like this:

{
    "foo": <very_long_text>
    "bar": <something_of_interest_for_the_test>
}

and what I get in the monitored [request HTTPBody] is a UUID: D68DD094-EAB4-4CEA-B401-AB1FA21BB34A

@tcamin
Copy link
Member

tcamin commented Feb 23, 2024

The logic should be right, I've slightly modified the implementation which should address the issue you are experiencing. Let me know if it works now.

@fermoya
Copy link
Author

fermoya commented Feb 26, 2024

Thanks @tcamin . I've updated my dependency to point at 985d63ec9a6080aeacbc2ca9d76b86cf2cea189e but unfortunately I still see the same issue.

What is it that you tweaked?

@tcamin
Copy link
Member

tcamin commented Feb 26, 2024

Same issue as in getting UUID or empty body?

@fermoya
Copy link
Author

fermoya commented Feb 26, 2024

Same issue as in getting UUID or empty body?

Getting UUID

@tcamin
Copy link
Member

tcamin commented Feb 27, 2024

Could you try again on e5c0f7f?

@fermoya
Copy link
Author

fermoya commented Feb 28, 2024

hey same issue on e5c0f7f4bd343627e55aecc39b76c39b32c8b444, I'm getting a UUID:

(lldb) po _originalRequest.HTTPBody
E8A5F5B2-65EF-432D-B7C4-F26E44E8DFA3

@magauran
Copy link

magauran commented Mar 5, 2024

@tcamin it seems that the properties saved in SBTRequestPropertyStorage from the app process are not visible in the UI Tests process.

@AhmedAshraf605
Copy link

@tcamin we have the same issue, any updates about the fix

@tcamin
Copy link
Member

tcamin commented Mar 19, 2024

Hi! Sorry for the late reply. It would help if you could provide a way to replicate this locally, ideally by adding a failing test to the libary.

@AhmedAshraf605
Copy link

@tcamin We appreciate your support and adding this test will help reproduce the issue locally. Please add the following test to DownloadUploadTests:

func testMonitorPostRequestWithHTTPLargeBodyInAppProcess() {

        let largeBody = String(repeating: "a", count: 20000)
        let matchingRequest = SBTRequestMatch(url: "httpbin.org", method: "POST")
        app.monitorRequests(matching: matchingRequest)

        XCTAssertTrue(app.tables.firstMatch.staticTexts["executePostDataTaskRequestWithLargeHTTPBody"].waitForExistence(timeout: 5))
        app.tables.firstMatch.staticTexts["executePostDataTaskRequestWithLargeHTTPBody"].tap()

        XCTAssertTrue(app.waitForMonitoredRequests(matching: matchingRequest, timeout: 10))
        let requests = app.monitoredRequestsFlushAll()
        XCTAssertEqual(requests.count, 1)

        print(requests.map(\.debugDescription))

        for request in requests {
            guard let httpBody = request.request?.httpBody else {
                XCTFail("Missing http body")
                continue
            }

            XCTAssertEqual(String(data: httpBody, encoding: .utf8), largeBody)

            XCTAssert((request.responseString()!).contains("httpbin.org"))
            XCTAssert(request.timestamp > 0.0)
            XCTAssert(request.requestTime > 0.0)
        }

        XCTAssert(app.stubRequestsRemoveAll())
        XCTAssert(app.monitorRequestRemoveAll())
    }

and add in SBTTableViewController

@objc func executePostDataTaskRequestWithLargeHTTPBody() {
        let largeBody = String(repeating: "a", count: 20000)
        dataTaskNetwork(urlString: "https://httpbin.org/post", httpMethod: "POST", httpBody: largeBody)
    }

The issue is that the request being fired is from the app process and not from the UITest process. As a result, we are unable to obtain the original request body.

@AhmedOS
Copy link
Contributor

AhmedOS commented Mar 26, 2024

@fermoya @magauran
Try this.

@fermoya
Copy link
Author

fermoya commented Mar 27, 2024

this is working @AhmedAshraf605 , thanks for the contribution 🙌

@tcamin will you cut a new version soon?

@tcamin
Copy link
Member

tcamin commented Mar 27, 2024

Hi! If everything works on our tests suites for a few days I will release a new version in the coming week.

@tcamin tcamin closed this as completed Mar 27, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants