This week I've mostly been working on this issue from Hurl. It proposes a new feature which allows users to query the IP address of the response and assert on it.
Support ip query for getting resolved response IP
#3106
A proposal to add an ip
query
GET https://foo.com
HTTP 200
[Asserts]
ip == "192.168.0.1"
GET https://foo.com
HTTP 200
[Asserts]
ip matches /2001:0000:130F:0000:0000:09C0:876A:\d*/
In libcurl
the corresponding call is CURLINFO_PRIMARY_IP
.
There is also a CURLINFO_LOCAL_IP
but I've the impression that user expectation is more on primary ip.
Question: what's about port ? Does the query ip
exctract the IP address and the port (192.168.0.01:8080
), or do we have a separate port
query that we can do latter?
GET https://foo.com
HTTP 200
[Asserts]
ip == "192.168.0.1"
port == 8080
With ip
/port
as separated queries, we can also have isIPv6
and isIPv4
predicates:
GET https://foo.com
HTTP 200
[Asserts]
ip isIPv6
Idea from @lepapareil 😎
</div>
<div class="gh-btn-container"><a class="gh-btn" href="https://github.com/Orange-OpenSource/hurl/issues/3106">View on GitHub</a></div>
I decided to really break it down into smaller PRs since there's going to be quite a lot of work to do.
As expected, since I'm moving into a new territory of the project, this would be a bumpy start. Luckily the maintainer gave me some guidance to work with.
🔧 Modify the Response
Module (Link)
The first step was to modify the Response
module. This was surprisingly easy: I added an ip_addr
field to the Response
struct and followed the breadcrumb of the Rust compiler. Quickly, I was able to figure out where the code should go.
One issue with it was that libcurl only gives you a string slice (&str
) of the IP address. So if I want to store it using the standard library enum std::net::IpAddr
, you have to convert it, and this conversion could fail. The maintainer suggested we create an intermediate struct for the response module, and only convert it if it's necessary. This way, if the user doesn't have any assert on IP address, there wouldn't be any run time error even if the address is invalid.
We had some more discussion on the specifics, but nothing major happened afterwards.
📝 (Attempt to) Implement IP Address Asserts
The Asserts
field in Hurl allows you to specify conditions which the response has to meet. It's an extremely useful feature for testing.
I used a similar strategy as a start - I found an enum called QueryValue
that seemed like it had to do with asserts, so I added another variant QueryValue::Ip
, and then I followed the compiler's messages. The problem this time was that, the messages took me all over the project and I was completely lost. It was so overwhelming that I had to pause.
Feeling confused, I spent quite some time reading the code. Although I still can't say I fully understand it, I made a simple diagram to help me visualize it:
Obviously, this is overly-simplified and may not even be correct. But the idea is that some kind of information is taken from both the response and the Hurl file. Then they are processed into results and asserts are performed between these results.
After some tinkering, I had the basic assert feature working:
There's still problem: As a part of the feature request, the maintainer wants to also be able to assert the IP version , i.e. IPv4/IPv6. In this context, it makes more sense to model these queries into std::net::IpAddr
, since it's an enum with already built-in variants IpAddr::V4
and 'IpAddr::V6'. However, in order to support certain assert features like contains
or matches
, these queries have to be strings.
Another issue was with IPv6 abbreviation. For example:
2001:0DB8:0032:0000:0000:0000:0000:FFFF
2001:0DB8:0032:0:0:0:0:FFFF
2001:0DB8:32:0:0:0:0:FFFF
2001:DB8:32::FFFF
All of the above are the same IP address. If we want to implement it as a string, users might not know what type of abbreviation to expect
I posted another comment about this situation and this is where I'm at right now. Let's see what the maintainer would say 😆
Top comments (0)