Skip to content

Commit 0cf0dbd

Browse files
christophechevalierZorin95670
authored andcommitted
feat(hpp): rename to http-plugin and add HttpTaskPlugin
1 parent dff9f30 commit 0cf0dbd

File tree

11 files changed

+564
-33
lines changed

11 files changed

+564
-33
lines changed

.github/workflows/http-provider-pull-request.yml renamed to .github/workflows/http-plugin-pull-request.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: 'Check Pull Request for plugin: http provider'
1+
name: 'Check Pull Request for plugin: http'
22

33
on:
44
pull_request:
@@ -47,7 +47,7 @@ jobs:
4747

4848
- name: Extract summary from pitest
4949
run: |
50-
echo "<html><head></head><body><h1>Pit Test Coverage Report: http-provider</h1><h3>Project Summary</h3>" > pitest.html
50+
echo "<html><head></head><body><h1>Pit Test Coverage Report: http-plugin</h1><h3>Project Summary</h3>" > pitest.html
5151
perl -0777 -ne 'print "$1\n" if /(<table>.*?<\/table>)/s' hpp/target/pit-reports/index.html >> pitest.html
5252
echo "</body></html>" >> pitest.html
5353

.github/workflows/sonar.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ jobs:
2424
with:
2525
node-version: '18'
2626

27-
- name: Start fake HTTP server for http-provider
27+
- name: Start fake HTTP server for http-plugin
2828
working-directory: hpp/src/test/fake-http-server
2929
run: |
3030
npm install

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,14 @@ Each plugin is maintained in a dedicated subdirectory and follows the same struc
1313
| Name | Description |
1414
| ------ | ------------------------------------------------------------------------- |
1515
| `cmtp` | Task plugin to copy and transform context values using Jinjava templates. |
16+
| `hpp` | Task plugin to execute configurable HTTP requests within task lifecycles. |
1617
| `jptp` | Task plugin to parse a JSON string from the context. |
1718

1819
### **📦 Provider plugins**
1920

20-
| Name | Description |
21-
| ----- | ----------------------------------------------------------------------------- |
22-
| `hpp` | Provider plugin to interact with configurable HTTP REST APIs (CRUD, mapping). |
21+
| Name | Description |
22+
| ----- | ---------------------------------------------------------------------------------------------- |
23+
| `hpp` | Provider plugin to interact with configurable HTTP REST APIs (CRUD, mapping, Jinja rendering). |
2324

2425
### **🧩 Validation Plugins**
2526

hpp/README.md

Lines changed: 73 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
1-
# 🌐 HttpProviderPlugin
1+
# 🌐 Http Plugin (hpp)
2+
3+
The `hpp` module provides HTTP-related plugins for LinID. It currently includes:
4+
5+
- **HttpProviderPlugin**: A provider plugin for CRUD operations over HTTP REST APIs with response mapping into dynamic entities.
6+
- **HttpTaskPlugin**: A task plugin for executing HTTP requests within task lifecycles.
7+
8+
## HttpProviderPlugin
29

310
The `HttpProviderPlugin` is a provider plugin designed to interact with configurable HTTP REST APIs, supporting full CRUD operations and response mapping into dynamic entities.
411

@@ -101,7 +108,7 @@ entities:
101108
### Configuration Fields
102109
103110
| Key | Required | Description |
104-
| ------------------------------------- | -------- |----------------------------------------------------------------------------------------------|
111+
| ------------------------------------- | -------- | -------------------------------------------------------------------------------------------- |
105112
| `baseUrl` | ✅ | Base URL of the HTTP API |
106113
| `headers` | ❌ | Optional HTTP headers (e.g., `Content-Type`, `Authorization`) |
107114
| `disabledRoutes` | ❌ | List of disabled actions for the entity (e.g., `patch`, `findAll`) |
@@ -113,7 +120,6 @@ entities:
113120
| `result` | ❌ | Expression evaluated to verify success (e.g., for `delete`) |
114121
| `page`, `size`, `total`, `itemsCount` | ❌ | Pagination info for `findAll`; mapping can use `index` for iterating items. |
115122

116-
117123
Voici un encadré clair que tu peux insérer dans ton README pour indiquer que **PATCH n’est plus supporté** :
118124

119125
---
@@ -122,9 +128,9 @@ Voici un encadré clair que tu peux insérer dans ton README pour indiquer que *
122128

123129
The `HttpProviderPlugin` **does not support the PATCH method**.
124130

125-
* Any configuration or task using `PATCH` will **throw an exception** if invoked.
126-
* Use `POST` for creation or `PUT` for updates instead.
127-
* Ensure that `patch` is included in `disabledRoutes` for your entities to prevent accidental usage:
131+
- Any configuration or task using `PATCH` will **throw an exception** if invoked.
132+
- Use `POST` for creation or `PUT` for updates instead.
133+
- Ensure that `patch` is included in `disabledRoutes` for your entities to prevent accidental usage:
128134

129135
```yaml
130136
entities:
@@ -134,7 +140,7 @@ entities:
134140
disabledRoutes: ['patch']
135141
```
136142

137-
* If you previously relied on PATCH for partial updates, you should migrate your logic to use full `PUT` updates or a custom workflow.
143+
- If you previously relied on PATCH for partial updates, you should migrate your logic to use full `PUT` updates or a custom workflow.
138144

139145
This explicitly prevents runtime errors and ensures consistency across all entity operations.
140146

@@ -184,6 +190,66 @@ This `json-parsing` task (from the jptp plugin) converts raw HTTP responses into
184190

185191
---
186192

193+
## HttpTaskPlugin
194+
195+
The `HttpTaskPlugin` is a task plugin that executes HTTP requests defined in task configuration. It allows performing HTTP calls at any point in the task lifecycle.
196+
197+
### ✅ Use Case
198+
199+
Use this plugin when you need to:
200+
201+
- Execute an HTTP call as a side-effect during entity processing (e.g., notify an external system).
202+
- Fetch data from an external API and store it in the execution context for subsequent tasks.
203+
- Chain HTTP calls with other task plugins (e.g., `json-parsing`, `context-mapping`).
204+
205+
### 🔧 Configuration
206+
207+
```yaml
208+
tasks:
209+
- type: http
210+
name: call-external-api
211+
url: 'http://example.com/api/resource'
212+
method: 'POST'
213+
headers:
214+
Content-Type: application/json
215+
body: '{"key": "{{ entity.value }}"}'
216+
phases: ['beforeCreate']
217+
```
218+
219+
### Configuration Fields
220+
221+
| Key | Required | Description |
222+
| --------- | -------- | ------------------------------------------------- |
223+
| `url` | ✅ | Full URL to call (supports Jinja templating) |
224+
| `method` | ✅ | HTTP method (`GET`, `POST`, `PUT`, `DELETE`) |
225+
| `headers` | ❌ | Optional HTTP headers (e.g., `Content-Type`) |
226+
| `body` | ❌ | Optional request body (supports Jinja templating) |
227+
228+
### 🛠 Behavior
229+
230+
- The plugin executes the configured HTTP request.
231+
- The raw HTTP response is stored in the execution context under the key `response`.
232+
- The `url` and `body` fields support Jinja templating, allowing dynamic values based on entity attributes and context.
233+
- HTTP errors (4xx, 5xx) throw an `ApiException` with the corresponding `hpp.error*` i18n key.
234+
235+
### Example: Chaining with json-parsing
236+
237+
```yaml
238+
tasks:
239+
- type: http
240+
name: fetch-data
241+
url: 'http://api.example.com/data/{{ context.id }}'
242+
method: GET
243+
phases: ['beforeResponseMappingFindById']
244+
- type: json-parsing
245+
name: parse-data
246+
source: response
247+
destination: response
248+
phases: ['beforeResponseMappingFindById']
249+
```
250+
251+
---
252+
187253
## 🧪 How to Run Tests
188254

189255
To run the tests including the HTTP fake server:

hpp/pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
<groupId>io.github.linagora.linid.im</groupId>
1111
<artifactId>hpp</artifactId>
1212
<version>0.2.2</version>
13-
<name>http-provider</name>
14-
<description>Plugin to manage http provider</description>
13+
<name>http-plugin</name>
14+
<description>Plugin for HTTP provider and task operations</description>
1515
<url>https://github.com/linagora/linid-im-api-community-plugins</url>
1616
<licenses>
1717
<license>
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*
2+
* Copyright (C) 2020-2026 Linagora
3+
*
4+
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
5+
* Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option)
6+
* any later version, provided you comply with the Additional Terms applicable for LinID Identity Manager software by
7+
* LINAGORA pursuant to Section 7 of the GNU Affero General Public License, subsections (b), (c), and (e), pursuant to
8+
* which these Appropriate Legal Notices must notably (i) retain the display of the "LinID™" trademark/logo at the top
9+
* of the interface window, the display of the “You are using the Open Source and free version of LinID™, powered by
10+
* Linagora © 2009–2013. Contribute to LinID R&D by subscribing to an Enterprise offer!” infobox and in the e-mails
11+
* sent with the Program, notice appended to any type of outbound messages (e.g. e-mail and meeting requests) as well
12+
* as in the LinID Identity Manager user interface, (ii) retain all hypertext links between LinID Identity Manager
13+
* and https://linid.org/, as well as between LINAGORA and LINAGORA.com, and (iii) refrain from infringing LINAGORA
14+
* intellectual property rights over its trademarks and commercial brands. Other Additional Terms apply, see
15+
* <http://www.linagora.com/licenses/> for more details.
16+
*
17+
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
18+
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
19+
* details.
20+
*
21+
* You should have received a copy of the GNU Affero General Public License and its applicable Additional Terms for
22+
* LinID Identity Manager along with this program. If not, see <http://www.gnu.org/licenses/> for the GNU Affero
23+
* General Public License version 3 and <http://www.linagora.com/licenses/> for the Additional Terms applicable to the
24+
* LinID Identity Manager software.
25+
*/
26+
27+
package io.github.linagora.linid.im.hpp;
28+
29+
import io.github.linagora.linid.im.corelib.plugin.config.dto.TaskConfiguration;
30+
import io.github.linagora.linid.im.corelib.plugin.entity.DynamicEntity;
31+
import io.github.linagora.linid.im.corelib.plugin.task.TaskExecutionContext;
32+
import io.github.linagora.linid.im.corelib.plugin.task.TaskPlugin;
33+
import io.github.linagora.linid.im.hpp.service.HttpService;
34+
import org.springframework.beans.factory.annotation.Autowired;
35+
import org.springframework.lang.NonNull;
36+
import org.springframework.stereotype.Component;
37+
38+
/**
39+
* Task plugin that executes HTTP requests defined in task configuration.
40+
*
41+
* <p>This plugin delegates to {@link HttpService} which reads {@code url}, {@code method},
42+
* and optionally {@code body} and {@code headers} from the task configuration options,
43+
* performs the HTTP request, and the raw response is stored in the execution context
44+
* under the key {@code "response"}.
45+
*/
46+
@Component
47+
public class HttpTaskPlugin implements TaskPlugin {
48+
49+
private static final String RESPONSE = "response";
50+
51+
private final HttpService httpService;
52+
53+
/**
54+
* Default constructor.
55+
*
56+
* @param httpService Service responsible for performing HTTP requests.
57+
*/
58+
@Autowired
59+
public HttpTaskPlugin(final HttpService httpService) {
60+
this.httpService = httpService;
61+
}
62+
63+
@Override
64+
public boolean supports(final @NonNull String type) {
65+
return "http".equalsIgnoreCase(type);
66+
}
67+
68+
@Override
69+
public void execute(final TaskConfiguration configuration,
70+
final DynamicEntity entity,
71+
final TaskExecutionContext context) {
72+
String response = httpService.request(context, entity, configuration);
73+
context.put(RESPONSE, response);
74+
}
75+
}

hpp/src/main/java/io/github/linagora/linid/im/hpp/service/HttpService.java

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,22 +26,22 @@
2626

2727
package io.github.linagora.linid.im.hpp.service;
2828

29+
import io.github.linagora.linid.im.corelib.plugin.config.dto.PluginConfiguration;
2930
import io.github.linagora.linid.im.corelib.plugin.config.dto.ProviderConfiguration;
3031
import io.github.linagora.linid.im.corelib.plugin.entity.DynamicEntity;
3132
import io.github.linagora.linid.im.corelib.plugin.task.TaskExecutionContext;
3233
import io.github.linagora.linid.im.hpp.model.EndpointConfiguration;
3334

3435
/**
35-
* Functional interface for performing HTTP requests in a dynamic and configurable way.
36+
* Service for performing HTTP requests in a dynamic and configurable way.
3637
*
3738
* <p>This service abstracts the execution of HTTP calls based on dynamic runtime context,
3839
* provider configuration, and endpoint configuration. It supports templated input using engines like Jinjava.
3940
*/
40-
@FunctionalInterface
4141
public interface HttpService {
4242

4343
/**
44-
* Executes an HTTP request based on the provided context and configurations.
44+
* Executes an HTTP request based on the provided context and provider/endpoint configurations.
4545
*
4646
* @param context the current execution context of the task; may contain runtime variables
4747
* @param configuration the global provider configuration (e.g., headers, base URL, credentials)
@@ -55,4 +55,19 @@ String request(TaskExecutionContext context,
5555
EndpointConfiguration endpointConfiguration,
5656
String action,
5757
DynamicEntity entity);
58+
59+
/**
60+
* Executes an HTTP request based on a plugin configuration.
61+
*
62+
* <p>This method extracts {@code url}, {@code method}, {@code body}, and {@code headers} from the
63+
* given configuration. The URL and body support Jinja templating.
64+
*
65+
* @param context the current execution context; may contain runtime variables for templating
66+
* @param entity the entity involved in the request; used for templating
67+
* @param configuration the plugin configuration containing url, method, body, and optional headers
68+
* @return the raw response body as a {@link String}
69+
*/
70+
String request(TaskExecutionContext context,
71+
DynamicEntity entity,
72+
PluginConfiguration configuration);
5873
}

0 commit comments

Comments
 (0)