Repository: mirumee/ariadne-codegen (python)

Issue:
Support disabling SSL cert verification for given remote GraphQL schemas
[Discussed here](https://github.com/mirumee/ariadne/discussions/1061)

It should be possible to disable ssh verification in pyproject.toml for given schema in cases where SSL cert is self-signed (eg. running https over internal network).

Pull request description:
Add remote_schema_verify_ssl option
resolves #105 

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index aa2a0c0..2d1d798 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,7 @@
 - Fixed annotations for lists.
 - Fixed support of custom operation types names.
 - Unlocked versions of black, isort, autoflake and dev dependencies
+- Added `remote_schema_verify_ssl` option.
 
 
 ## 0.4.0 (2023-03-20)
diff --git a/README.md b/README.md
index cc31be9..9b640e6 100644
--- a/README.md
+++ b/README.md
@@ -47,6 +47,7 @@ One of the following 2 parameters is required, in case of providing both of them
 Optional settings:
 
 - `remote_schema_headers` - extra headers that are passed along with introspection query, eg. `{"Authorization" = "Bearer: token"}`. To include an environment variable in a header value, prefix the variable with `$`, eg. `{"Authorization" = "$AUTH_TOKEN"}`
+- `remote_schema_verify_ssl` (defaults to `true`) - a flag that specifies wheter to verify ssl while introspecting remote schema
 - `target_package_name` (defaults to `"graphql_client"`) - name of generated package
 - `target_package_path` (defaults to cwd) - path where to generate package
 - `client_name` (defaults to `"Client"`) - name of generated client class
@@ -220,7 +221,7 @@ Instead of generating client, you can generate file with a copy of GraphQL schem
 ariadne-codegen graphqlschema
 ```
 
-`graphqlschema` mode reads configuration from the same place as [`client`](#configuration) but uses only `schema_path`, `remote_schema_url`, `remote_schema_headers` options with addition to some extra options specific to it:    
+`graphqlschema` mode reads configuration from the same place as [`client`](#configuration) but uses only `schema_path`, `remote_schema_url`, `remote_schema_headers` and `remote_schema_verify_ssl` options with addition to some extra options specific to it:    
 
 - `target_file_path` (defaults to `"schema.py"`) - destination path for generated file
 - `schema_variable_name` (defaults to `"schema"`) - name for schema variable, must be valid python identifier
diff --git a/ariadne_codegen/main.py b/ariadne_codegen/main.py
index 40891ac..3e6b76f 100644
--- a/ariadne_codegen/main.py
+++ b/ariadne_codegen/main.py
@@ -42,7 +42,9 @@ def client(config_dict):
         schema_source = settings.schema_path
     else:
         schema = get_graphql_schema_from_url(
-            url=settings.remote_schema_url, headers=settings.remote_schema_headers
+            url=settings.remote_schema_url,
+            headers=settings.remote_schema_headers,
+            verify_ssl=settings.remote_schema_verify_ssl,
         )
         schema_source = settings.remote_schema_url
 
@@ -90,7 +92,9 @@ def graphql_schema(config_dict):
         get_graphql_schema_from_path(settings.schema_path)
         if settings.schema_path
         else get_graphql_schema_from_url(
-            url=settings.remote_schema_url, headers=settings.remote_schema_headers
+            url=settings.remote_schema_url,
+            headers=settings.remote_schema_headers,
+            verify_ssl=settings.remote_schema_verify_ssl,
         )
     )
 
diff --git a/ariadne_codegen/schema.py b/ariadne_codegen/schema.py
index 1d09f0d..f6e56aa 100644
--- a/ariadne_codegen/schema.py
+++ b/ariadne_codegen/schema.py
@@ -41,19 +41,22 @@ def get_graphql_queries(queries_path: str) -> Tuple[DefinitionNode, ...]:
 
 
 def get_graphql_schema_from_url(
-    url: str, headers: Optional[Dict[str, str]] = None
+    url: str, headers: Optional[Dict[str, str]] = None, verify_ssl: bool = True
 ) -> GraphQLSchema:
-    return build_client_schema(introspect_remote_schema(url=url, headers=headers))
+    return build_client_schema(
+        introspect_remote_schema(url=url, headers=headers, verify_ssl=verify_ssl)
+    )
 
 
 def introspect_remote_schema(
-    url: str, headers: Optional[Dict[str, str]] = None
+    url: str, headers: Optional[Dict[str, str]] = None, verify_ssl: bool = True
 ) -> IntrospectionQuery:
     try:
         response = httpx.post(
             url,
             json={"query": get_introspection_query(descriptions=False)},
             headers=headers,
+            verify=verify_ssl,
         )
     except httpx.InvalidURL as exc:
         raise IntrospectionError(f"Invalid remote schema url: {url}") from exc
diff --git a/ariadne_codegen/settings.py b/ariadne_codegen/settings.py
index 133f19e..c11c70c 100644
--- a/ariadne_codegen/settings.py
+++ b/ariadne_codegen/settings.py
@@ -24,6 +24,7 @@ class BaseSettings:
     schema_path: Optional[str] = None
     remote_schema_url: Optional[str] = None
     remote_schema_headers: dict = field(default_factory=dict)
+    remote_schema_verify_ssl: bool = True
 
     def __post_init__(self):
         if not self.schema_path and not self.remote_schema_url:


Test patch:
diff --git a/tests/test_schema.py b/tests/test_schema.py
index 61ce581..02502bc 100644
--- a/tests/test_schema.py
+++ b/tests/test_schema.py
@@ -345,6 +345,21 @@ def test_introspect_remote_schema_uses_provided_headers(mocker):
     assert mocked_post.called_with(headers={"test": "value"})
 
 
+@pytest.mark.parametrize("verify_ssl", [True, False])
+def test_introspect_remote_schema_uses_provided_verify_ssl_flag(verify_ssl, mocker):
+    mocked_post = mocker.patch(
+        "ariadne_codegen.schema.httpx.post",
+        return_value=httpx.Response(
+            status_code=200, content='{"data": {"__schema": {}}}'
+        ),
+    )
+
+    introspect_remote_schema("http://testserver/graphql/", verify_ssl=verify_ssl)
+
+    assert mocked_post.called
+    assert mocked_post.called_with(verify=verify_ssl)
+
+
 def test_get_graphql_queries_returns_schema_definitions_from_single_file(
     single_file_query,
 ):