Midnighter / structurizr-python

A Python 3 port of Simon Brown's Structurizr diagrams-as-code architecture description tool.
https://structurizr.com/
Apache License 2.0
65 stars 16 forks source link

Issue 38: fix API change in httpx library which broke API calls #39

Closed yt-ms closed 3 years ago

yt-ms commented 3 years ago

httpx.URL class had its API changed in version 0.15 to change full_path to raw_path. This PR updates StructurizrClient to work with this new httpx API.


THIS SOFTWARE IS CONTRIBUTED SUBJECT TO THE TERMS OF THE Apache License v.2.0. YOU MAY OBTAIN A COPY OF THE LICENSE AT https://www.apache.org/licenses/LICENSE-2.0.

THIS SOFTWARE IS LICENSED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AND ANY WARRANTY OF NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THIS SOFTWARE MAY BE REDISTRIBUTED TO OTHERS ONLY BY EFFECTIVELY USING THIS OR ANOTHER EQUIVALENT DISCLAIMER IN ADDITION TO ANY OTHER REQUIRED LICENSE TERMS.

codecov-io commented 3 years ago

Codecov Report

Merging #39 into devel will increase coverage by 0.84%. The diff coverage is 40.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##            devel      #39      +/-   ##
==========================================
+ Coverage   82.42%   83.27%   +0.84%     
==========================================
  Files          63       63              
  Lines        1696     1698       +2     
  Branches      141      141              
==========================================
+ Hits         1398     1414      +16     
+ Misses        272      258      -14     
  Partials       26       26              
Impacted Files Coverage Δ
src/structurizr/api/structurizr_client.py 59.54% <40.00%> (+11.47%) :arrow_up:

Continue to review full report at Codecov.

Legend - Click here to learn more Δ = absolute <relative> (impact), ø = not affected, ? = missing data Powered by Codecov. Last update cfcb9b9...536fd5b. Read the comment docs.

yt-ms commented 3 years ago

PR looks great. Thank you also for adding relevant tests! My only doubt right now is decoding using the ASCII codec. I'm not sure it's relevant here but the URL may contain unicode characters which are then % URL encoded before being encoded as bytes. So do we need a step after decoding using ASCII that reverts % URL encodings? I should probably ask Simon Brown or did you look at the Java client?

I did have a look at the Java client, but it uses HttpUriRequestBase.getPath() and the docs are not particularly helpful. Looing at the C# client then it looks (e.g. in manageLockForWorkspace()) like it does want unescaped. I just did a quick check as to what httpx.Request does with raw_path and it does gives you it unescaped so I think we should be good:

>>> request = client._client.build_request("GET", "test?abc&q=123+def")
>>> request
<Request('GET', 'http://a.b.c:8080/api/test?abc&q=123+def')>
>>> request.url
URL('http://a.b.c:8080/api/test?abc&q=123+def')
>>> request.url.raw_path.decode("ascii")
'/api/test?abc&q=123+def'
yt-ms commented 3 years ago

I've just added a defensive test to validate that httpx.Request.raw_path doesn't escape characters (also in case this changes in the future).

Midnighter commented 3 years ago

Your test URL doesn't contain characters that need to be escaped. With httpx 0.13.3

>>> url = httpx.URL('http://example.com:8080/api/test?q=motörhead')
>>> url2.full_path
'/api/test?q=mot%C3%B6rhead'

with httpx 0.16.1

>>> url = httpx.URL('http://example.com:8080/api/test?q=motörhead')
>>> url2.raw_path.decode('ascii')
'/api/test?q=mot%C3%B6rhead'

So that's consistent. I wasn't sure if previous versions were returning unicode and what we needed exactly for the structurizr digest header.

As the last thing, could you include a case that actually requires % URL encoding to the tests, please, and in the setup.cfg pin

    httpx ~= 0.16

Cheers!

yt-ms commented 3 years ago

Your test URL doesn't contain characters that need to be escaped. With httpx 0.13.3

Ah, that kind of escaping. I've updated the test to have non-ASCII characters, but it's hard to actually try that against a real Structurizr server to make sure the X-Authorization is accepted.

I've also now pinned the httpx version.

Midnighter commented 3 years ago

Ah, that kind of escaping. I've updated the test to have non-ASCII characters, but it's hard to actually try that against a real Structurizr server to make sure the X-Authorization is accepted.

The repo has the information for an open source workspace embedded as GitHub secrets. So we can create an integration test for it. However, I would merge this now and create an integration test only if it comes up as a problem in future.

Midnighter commented 3 years ago

Btw, httpx is quite close to a 1.0 release so hopefully no more API changes on the horizon :wink: