0
# Configuration Parser
1
2
The NginxParser class handles the fine details of parsing and modifying nginx configuration files. It provides high-level operations for working with nginx server blocks, directives, and included files while maintaining the structure and formatting of configuration files.
3
4
## Capabilities
5
6
### Parser Initialization and Loading
7
8
Initialize the parser and load nginx configuration files into a parsed tree structure.
9
10
```python { .api }
11
class NginxParser:
12
"""Class handles parsing nginx configuration files.
13
14
Args:
15
root: Absolute path to server root directory
16
17
Attributes:
18
parsed: dict[str, UnspacedList] - Mapping of file paths to parsed trees
19
root: str - Normalized absolute path to server root
20
config_root: str - Configuration root directory
21
"""
22
23
def __init__(self, root: str) -> None:
24
"""Initialize parser with server root directory."""
25
26
def load(self) -> None:
27
"""Load nginx files into parsed tree.
28
29
Parses nginx.conf and all included files recursively.
30
"""
31
32
@property
33
def http_path(self) -> str:
34
"""Path to file containing nginx http block.
35
36
Returns:
37
Filepath of file with http block
38
39
Raises:
40
errors.MisconfigurationError: No nginx http block found
41
"""
42
```
43
44
### Virtual Host Management
45
46
Extract and manage virtual host information from nginx configuration.
47
48
```python { .api }
49
def get_vhosts(self) -> list[VirtualHost]:
50
"""Get list of all virtual hosts found in nginx configuration.
51
52
Returns:
53
List of VirtualHost objects found in configuration
54
"""
55
56
def duplicate_vhost(self, vhost: VirtualHost,
57
remove_singleton_listen_params: bool = False,
58
only_directives: Optional[list[str]] = None) -> VirtualHost:
59
"""Duplicate a virtual host with optional filtering.
60
61
Args:
62
vhost: Virtual host to duplicate
63
remove_singleton_listen_params: Remove singleton listen parameters
64
only_directives: Only duplicate these directives if specified
65
66
Returns:
67
New duplicated VirtualHost object
68
"""
69
```
70
71
### Configuration Path Utilities
72
73
Handle file paths and configuration structure navigation.
74
75
```python { .api }
76
def abs_path(self, path: str) -> str:
77
"""Convert relative path to absolute path relative to root.
78
79
Args:
80
path: The path to convert
81
82
Returns:
83
Absolute path
84
"""
85
```
86
87
### Server Directive Management
88
89
Add, update, and remove directives from nginx server blocks.
90
91
```python { .api }
92
def add_server_directives(self, vhost: VirtualHost, directives: list[list[str]],
93
insert_at_top: bool = False) -> None:
94
"""Add directives to server block.
95
96
Args:
97
vhost: Virtual host to modify
98
directives: List of directive lists to add
99
insert_at_top: Insert at top of server block if True
100
101
Raises:
102
errors.MisconfigurationError: Problem adding directives
103
"""
104
105
def update_or_add_server_directives(self, vhost: VirtualHost,
106
directives: list[list[str]]) -> None:
107
"""Update existing directives or add new ones.
108
109
Args:
110
vhost: Virtual host to modify
111
directives: List of directive lists to update/add
112
113
Raises:
114
errors.MisconfigurationError: Problem updating directives
115
"""
116
117
def remove_server_directives(self, vhost: VirtualHost, directive: str,
118
match_func: Optional[Callable[[Any], bool]] = None) -> None:
119
"""Remove server directives matching criteria.
120
121
Args:
122
vhost: Virtual host to modify
123
directive: Name of directive to remove
124
match_func: Optional function to match specific directives
125
126
Raises:
127
errors.MisconfigurationError: Problem removing directives
128
"""
129
130
def parse_server(self, server: UnspacedList) -> dict[str, Any]:
131
"""Parse server block directives and extract configuration.
132
133
Args:
134
server: Parsed server block as UnspacedList
135
136
Returns:
137
Dictionary containing parsed server configuration with keys:
138
- addrs: List of addresses the server listens on
139
- ssl: Boolean indicating if SSL is enabled
140
- names: Set of server names
141
142
Raises:
143
errors.MisconfigurationError: Invalid server block structure
144
"""
145
```
146
147
### SSL Configuration Detection
148
149
Detect SSL-related configuration in virtual hosts.
150
151
```python { .api }
152
def has_ssl_on_directive(self, vhost: VirtualHost) -> bool:
153
"""Check if virtual host has 'ssl on' directive.
154
155
Args:
156
vhost: Virtual host to check
157
158
Returns:
159
True if 'ssl on' directive is present
160
"""
161
```
162
163
### Configuration File Operations
164
165
Write parsed configuration back to files with proper formatting.
166
167
```python { .api }
168
def filedump(self, ext: str = 'tmp', lazy: bool = True) -> None:
169
"""Write parsed configuration back to files.
170
171
Args:
172
ext: File extension to use ('tmp' for temporary files, '' for original files)
173
lazy: Only dump files that have been modified if True
174
"""
175
```
176
177
## Internal Methods
178
179
```python { .api }
180
def _parse_recursively(self, filepath: str) -> None:
181
"""Parse nginx config files recursively by following include directives."""
182
183
def _parse_files(self, filepath: str) -> dict[str, UnspacedList]:
184
"""Parse files matching glob pattern."""
185
186
def _build_addr_to_ssl(self) -> dict[tuple[str, str], bool]:
187
"""Build map from address to SSL status."""
188
189
def _get_raw_servers(self) -> dict[str, Union[list[Any], UnspacedList]]:
190
"""Get map of unparsed server blocks."""
191
192
def _update_vhosts_addrs_ssl(self, vhosts: Iterable[VirtualHost]) -> None:
193
"""Update vhost addresses with global SSL status."""
194
195
def _get_included_directives(self, block: UnspacedList) -> UnspacedList:
196
"""Expand include directives by concatenating included file contents."""
197
```
198
199
## Utility Functions
200
201
```python { .api }
202
def get_best_match(target_name: str, names: Iterable[str]) -> tuple[Optional[str], Optional[str]]:
203
"""Get best matching server name for target.
204
205
Args:
206
target_name: Target domain name
207
names: Set of server names to match against
208
209
Returns:
210
Tuple of (match_type, matched_name) where match_type indicates
211
the type of match found and matched_name is the matching server name,
212
or (None, None) if no match is found
213
"""
214
215
def comment_directive(block: UnspacedList, index: int) -> None:
216
"""Comment out directive at specified index.
217
218
Args:
219
block: Configuration block
220
index: Index of directive to comment
221
"""
222
```
223
224
## Usage Examples
225
226
### Basic Parser Operations
227
228
```python
229
from certbot_nginx._internal.parser import NginxParser
230
231
# Initialize parser
232
parser = NginxParser('/etc/nginx')
233
234
# Load configuration files
235
parser.load()
236
237
# Get all virtual hosts
238
vhosts = parser.get_vhosts()
239
print(f"Found {len(vhosts)} virtual hosts")
240
241
# Show virtual host details
242
for vhost in vhosts:
243
print(f"File: {vhost.filep}")
244
print(f"Names: {vhost.names}")
245
print(f"SSL: {vhost.ssl}")
246
print(f"Addresses: {[str(addr) for addr in vhost.addrs]}")
247
```
248
249
### Adding Directives to Virtual Host
250
251
```python
252
# Select a virtual host
253
vhost = vhosts[0]
254
255
# Add SSL certificate directives
256
ssl_directives = [
257
['\n ', 'ssl_certificate', ' ', '/path/to/cert.pem'],
258
['\n ', 'ssl_certificate_key', ' ', '/path/to/key.pem']
259
]
260
261
parser.add_server_directives(vhost, ssl_directives)
262
263
# Write changes back to files
264
parser.filedump()
265
```
266
267
### Duplicating Virtual Hosts
268
269
```python
270
# Duplicate a virtual host for SSL configuration
271
original_vhost = vhosts[0]
272
ssl_vhost = parser.duplicate_vhost(original_vhost)
273
274
# Add SSL-specific directives to the duplicate
275
ssl_config = [
276
['\n ', 'listen', ' ', '443', ' ', 'ssl'],
277
['\n ', 'ssl_certificate', ' ', '/path/to/cert.pem'],
278
['\n ', 'ssl_certificate_key', ' ', '/path/to/key.pem']
279
]
280
281
parser.add_server_directives(ssl_vhost, ssl_config)
282
```
283
284
### Checking SSL Configuration
285
286
```python
287
for vhost in vhosts:
288
has_ssl_on = parser.has_ssl_on_directive(vhost)
289
print(f"VHost {vhost.filep} has 'ssl on': {has_ssl_on}")
290
```