..questions:: OK then. What happens when you select the "Manual proxy configuration"?
A good configuration design is to place all the proxy's manual configuration in a :term:`family`.
Let's create the :file:`dict/02-proxy_manual.yml` dictionary:
..code-block:: yaml
:caption:the the :file:`dict/02-proxy_manual.yml` file
---
version: '1.1'
proxy:
manual:
description: Manual proxy configuration
type: family
disabled:
type: jinja
jinja: |
{% if rougail.proxy.proxy_mode != 'Manual proxy configuration' %}
the proxy mode is not manual
{% endif %}
Well, if the user selects the "Manual proxy configuration" proxy mode, we want to see a new subfamily (that is, a new set of configuration variables) called `manual` to appear (which is disabled).
..glossary::
subfamily
A subfamily is just a family inside a family, a family that contains a family.
..questions:: What about this `Jinja` type?
If the :term:`Jinja` template returns some text, then the family will be `disabled`. Otherwise it is accessible.
Deactivating a family means that we will not be able to access it as well as the variables or families included in this family.
..note:: If the Jinja template does not return any text, the variable will be **enabled**.
Here we are using the Jinja condition statement.
..glossary::
Jinja
`Jinja <https://jinja.palletsprojects.com>`_ is a template engine.
we are using Jinja in a classical way, that is, Jinja allows us to handle different cases,
for example with the `if` statement.
The HTTP proxy configuration
------------------------------
In this family let's add a *subfamily* named `http_proxy`, containing the address and port configuration variables.
Let's create the :file:`dict/03-proxy_manual_http_proxy.yml` dictionary:
..code-block:: yaml
:caption:the the :file:`dict/02-proxy_manual.yml` file
:linenos:
---
version: '1.1'
proxy:
manual:
http_proxy:
description: HTTP Proxy
address:
description: HTTP address
type: domainname
port:
description: HTTP Port
type: port
default: '8080'
Both variables `address` and `port` have particular types (respectively `domainname` line 9 and `port` line 12) to validate the values configured by the user.
..note:: No need to specify the type of the `http_proxy` as a family type, because here we have declared variables inside of it.
Duplicating the HTTP configuration to HTTPS
---------------------------------------------
We then want to offer the user the possibility of providing the same proxy for the HTTPS requests. Let's create the :file:`dict/04-proxy_manual_http_use_for_https.yml` file:
Depending on the value of the `rougail.proxy.mandatory.use_for_https` variable, this family will appear or disappear (the `hidden` setting line 7). Unlike earlier, this time it is not necessary to use a Jinja function.
Let's notice that the family is not disabled because the variables will need to remain accessible (yet in `read-only` mode).
The address and port variables are copied from HTTP to HTTPS if `rougail.proxy.use_for_https` is set to `True`.
Now let's test all of it:
>>> from rougail import Rougail, RougailConfig
>>> from pprint import pprint
>>> RougailConfig['dictionaries_dir'] = ['dict']
>>> rougail = Rougail()
>>> config = rougail.get_config()
>>> config.property.read_only()
>>> pprint(config.value.get(), sort_dicts=False)
{'rougail.proxy.proxy_mode': 'No proxy'}
At this time the proxy is not configured yet, so we do not see any variables.
Let's look at what happens if we try to access the `rougail.proxy.manual` variable if we are not in manual mode:
tiramisu.error.ValueOptionError: "not valid" is an invalid domain name for "Address for which proxy will be desactivated", could be a IP, otherwise must start with lowercase characters followed by lowercase characters, number, "-" and "." characters are allowed
The authentification request
--------------------------------
Nothing special when creating the authentication request. To do this, let's create a `dict/08-proxy_prompt_authentication.yml` file:
{% if not rougail.proxy.dns_over_https.enable_dns_over_https %}
Enable DNS over HTTPS is False
{% endif %}
custom_dns_url:
description: Custom DNS URL
type: web_address
disabled:
type: jinja
params:
provider:
type: variable
variable: rougail.proxy.dns_over_https.provider
propertyerror: false
jinja: |
{% if provider is not defined or provider != 'Custom' %}
provider is not custom
{% endif %}
validators:
- type: jinja
jinja: |
{% if rougail.proxy.dns_over_https.custom_dns_url.startswith('http://') %}
only https is allowed
{% endif %}
.. FIXME : define validators
The only particularity here is that we added additional validation (validators) to the `custom_dns_url` variable. Only an address starting with `https://` is allowed (not `http://`).
----
The FoxyProxy type's proxy configuration
--------------------------------------------
Here is now the integration of part of the Firefox FoxyProxy plugin.
The idea is to have a namespace specific to FoxyProxy and to find in it part of the settings that we will have made in the main namespace.
This is what the page looks like:
..image:: images/foxyproxy.png
It is possible, in this plugin, to specify an unlimited number of proxies.
Our `proxy` family will no longer be of the `family` type as before but of another type : the :term:`leadership` type.
.. FIXME: expliquer ce qu'est le type leardership
Here is the complete content of the FoxyProxy type proxy configuration
(to be put in the `foxyproxy/00-base.yml` file):
..code-block:: yaml
:caption:the :file:``foxyproxy/00-base.yml`` file
:linenos:
---
version: '1.1'
proxy:
_type: leadership
title:
description: Title or Description
multi: true
color:
description: Color
type:
type: choice
choices:
- HTTP
- HTTPS/SSL
- SOCKS5
- SOCKS4
- PAC URL
- WPAD
- System (use system settings)
- Direct (no proxy)
default: Direct (no proxy)
address:
description: IP address, DNS name, server name
multi: true
disabled:
type: jinja
jinja: |
{% if foxyproxy.proxy.type not in ['HTTP', 'HTTPS/SSL', 'SOCKS5', 'SOCKS4'] %}
proxy does not need address
{% endif %}
default:
type: jinja
params:
firefox_address:
type: variable
variable: rougail.proxy.manual.http_proxy.address
propertyerror: false
jinja: |
{% if firefox_address is not undefined %}
{{ firefox_address }}
{% endif %}
port:
description: Port
type: port
default:
type: jinja
params:
firefox_port:
type: variable
variable: rougail.proxy.manual.http_proxy.port
propertyerror: false
jinja: |
{% if firefox_port is not undefined %}
{{ firefox_port }}
{% endif %}
disabled:
type: jinja
jinja: |
{% if foxyproxy.proxy.type not in ['HTTP', 'HTTPS/SSL', 'SOCKS5', 'SOCKS4'] %}
proxy does not need port
{% endif %}
username:
description: Username
type: unix_user
mandatory:
type: jinja
jinja: |
{% if foxyproxy.proxy.password %}
username is mandatory
{% endif %}
disabled:
type: jinja
jinja: |
{% if foxyproxy.proxy.type not in ['HTTP', 'HTTPS/SSL', 'SOCKS5', 'SOCKS4'] %}
proxy does not need username
{% endif %}
password:
description: Password
type: secret
disabled:
type: jinja
jinja: |
{% if foxyproxy.proxy.type not in ['HTTP', 'HTTPS/SSL', 'SOCKS5', 'SOCKS4'] %}
proxy does not need password
{% endif %}
url:
type: web_address
disabled:
type: jinja
jinja: |
{% if foxyproxy.proxy.type not in ['PAC URL', 'WPAD'] %}
proxy does not need url
{% endif %}
A few comments:
- in the `foxyproxy.proxy` :term:`leader` family there is a variable named `type` (line 4), this may conflict with the `type` attribute (specified line 10). In this case, to specify the type we use the `_type` attribute
- a :term:`follower` variable can also be multiple
(which is the case for `foxyproxy.proxy.address`)
-`foxyproxy.proxy.username` (line 62) becomes :term:`mandatory` if `foxyproxy.proxy.password`
is specified, in fact a password without a username is meaningless
The choice we made here is to make `foxyproxy.proxy.username`:term:`mandatory` if a password is specified in the `foxyproxy.proxy.password` variable.
It makes sense to have a username without a password (in this case the password will be requested when connecting to the proxy). But the opposite does not make sense.
From a user point of view this may seem disturbing (if you enter the password, you have to return to the previous option to specify the password).
It is possible to reverse the logic. If the `foxyproxy.proxy.username` variable is set, the `foxyproxy.proxy.password` variable becomes editable.
None of this two variables needs to be :term:`mandatory`.
If you prefer this option, here is a second extra dictionary :file:`foxyproxy/01-redefine.yml` which will redefine the behavior only of the `foxyproxy.proxy.username` and `foxyproxy.proxy.password` variables: