Skip to content

Commit 4dc0902

Browse files
committed
apply http data source service config to request
The generic http data source supports authentication config in the service config. This was not applied to the request, which now happens.
1 parent 1dea106 commit 4dc0902

File tree

3 files changed

+198
-3
lines changed

3 files changed

+198
-3
lines changed

inc/Config/DataSource/HttpDataSource.php

+42-2
Original file line numberDiff line numberDiff line change
@@ -98,11 +98,51 @@ protected static function get_service_config_schema(): array {
9898
return ConfigSchemas::get_http_data_source_service_config_schema();
9999
}
100100

101+
private static function get_auth_to_request_headers( array $service_config ): array {
102+
if ( ! isset( $service_config['auth'] ) ) {
103+
return [];
104+
}
105+
106+
$auth_headers = [];
107+
$auth = $service_config['auth'];
108+
109+
if ( $auth['type'] === 'bearer' ) {
110+
$auth_headers['Authorization'] = 'Bearer ' . $auth['value'];
111+
} elseif ( $auth['type'] === 'basic' ) {
112+
$auth_headers['Authorization'] = 'Basic ' . base64_encode( $auth['value'] );
113+
} elseif ( $auth['type'] === 'api-key' && $auth['add_to'] === 'header' ) {
114+
$auth_headers[$auth['key']] = $auth['value'];
115+
}
116+
117+
return $auth_headers;
118+
}
119+
120+
private static function add_auth_to_endpoint( string|null $endpoint, array $service_config ): string|null {
121+
if ( ! isset( $service_config['auth'] )
122+
|| $service_config['auth']['type'] !== 'api-key'
123+
|| $service_config['auth']['add_to'] !== 'queryparams'
124+
|| empty( $endpoint )
125+
) {
126+
return $endpoint;
127+
}
128+
129+
$query_string = $service_config['auth']['key'] . '=' . $service_config['auth']['value'];
130+
131+
return $endpoint . ( strpos( $endpoint, '?' ) === false ? '?' : '&' ) . $query_string;
132+
}
133+
101134
protected static function map_service_config( array $service_config ): array {
135+
$request_headers = $service_config['request_headers'] ?? [];
136+
$endpoint = $service_config['endpoint'] ?? null; // Invalid, but we won't guess it.
137+
138+
$auth_headers = self::get_auth_to_request_headers( $service_config );
139+
$request_headers = array_merge( $request_headers, $auth_headers );
140+
$endpoint = self::add_auth_to_endpoint( $endpoint, $service_config );
141+
102142
return [
103143
'display_name' => $service_config['display_name'] ?? static::SERVICE_NAME,
104-
'endpoint' => $service_config['endpoint'] ?? null, // Invalid, but we won't guess it.
105-
'request_headers' => $service_config['request_headers'] ?? [],
144+
'endpoint' => $endpoint,
145+
'request_headers' => $request_headers,
106146
];
107147
}
108148

inc/Validation/ConfigSchemas.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ private static function generate_http_data_source_service_config_schema(): array
152152
'__version' => Types::integer(),
153153
'auth' => Types::nullable(
154154
Types::object( [
155-
'add_to' => Types::nullable( Types::enum( 'header', 'query' ) ),
155+
'add_to' => Types::nullable( Types::enum( 'header', 'queryparams' ) ),
156156
'key' => Types::nullable( Types::skip_sanitize( Types::string() ) ),
157157
'type' => Types::enum( 'basic', 'bearer', 'api-key', 'none' ),
158158
'value' => Types::skip_sanitize( Types::string() ),

tests/inc/Config/HttpDataSourceTest.php

+155
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use PHPUnit\Framework\TestCase;
66
use RemoteDataBlocks\Tests\Mocks\MockDataSource;
7+
use RemoteDataBlocks\Tests\Mocks\MockValidator;
78
use WP_Error;
89

910
class HttpDataSourceTest extends TestCase {
@@ -67,4 +68,158 @@ public function testMigrateConfigMethodCanBeOverridden_user_id_is_not_an_integer
6768
$this->assertInstanceOf( WP_Error::class, $this->http_data_source );
6869
$this->assertSame( 'testUserId must be an integer', $this->http_data_source->get_error_message() );
6970
}
71+
72+
public function testBearerAuthHeaderIsAdded(): void {
73+
$config = [
74+
'service_config' => [
75+
'__version' => 1,
76+
'display_name' => 'Mock Data Source',
77+
'endpoint' => 'http://example.com',
78+
'auth' => [
79+
'type' => 'bearer',
80+
'value' => 'test-token',
81+
],
82+
],
83+
];
84+
$this->http_data_source = MockDataSource::create( $config );
85+
86+
$this->assertNotInstanceOf( WP_Error::class, $this->http_data_source );
87+
$headers = $this->http_data_source->get_request_headers();
88+
$this->assertIsArray( $headers );
89+
$this->assertArrayHasKey( 'Authorization', $headers );
90+
$this->assertSame( 'Bearer test-token', $headers['Authorization'] );
91+
}
92+
93+
public function testBasicAuthHeaderIsAdded(): void {
94+
$config = [
95+
'service_config' => [
96+
'__version' => 1,
97+
'display_name' => 'Mock Data Source',
98+
'endpoint' => 'http://example.com',
99+
'auth' => [
100+
'type' => 'basic',
101+
'value' => 'user:pass',
102+
],
103+
],
104+
];
105+
$this->http_data_source = MockDataSource::create( $config );
106+
107+
$this->assertNotInstanceOf( WP_Error::class, $this->http_data_source );
108+
$headers = $this->http_data_source->get_request_headers();
109+
$this->assertIsArray( $headers );
110+
$this->assertArrayHasKey( 'Authorization', $headers );
111+
$this->assertSame( 'Basic ' . base64_encode( 'user:pass' ), $headers['Authorization'] );
112+
}
113+
114+
public function testApiKeyHeaderIsAdded(): void {
115+
$config = [
116+
'service_config' => [
117+
'__version' => 1,
118+
'display_name' => 'Mock Data Source',
119+
'endpoint' => 'http://example.com',
120+
'auth' => [
121+
'type' => 'api-key',
122+
'add_to' => 'header',
123+
'key' => 'X-Api-Key',
124+
'value' => 'test-api-key',
125+
],
126+
],
127+
];
128+
$this->http_data_source = MockDataSource::create( $config );
129+
130+
$this->assertNotInstanceOf( WP_Error::class, $this->http_data_source );
131+
$headers = $this->http_data_source->get_request_headers();
132+
$this->assertIsArray( $headers );
133+
$this->assertArrayHasKey( 'X-Api-Key', $headers );
134+
$this->assertSame( 'test-api-key', $headers['X-Api-Key'] );
135+
}
136+
137+
public function testApiKeyQueryParamIsAdded(): void {
138+
$config = [
139+
'service_config' => [
140+
'__version' => 1,
141+
'display_name' => 'Mock Data Source',
142+
'endpoint' => 'http://example.com/data',
143+
'auth' => [
144+
'type' => 'api-key',
145+
'add_to' => 'queryparams',
146+
'key' => 'api_key',
147+
'value' => 'test-api-key',
148+
],
149+
],
150+
];
151+
$this->http_data_source = MockDataSource::create( $config );
152+
153+
$this->assertNotInstanceOf( WP_Error::class, $this->http_data_source );
154+
$endpoint = $this->http_data_source->get_endpoint();
155+
$this->assertSame( 'http://example.com/data?api_key=test-api-key', $endpoint );
156+
}
157+
158+
public function testApiKeyQueryParamIsAppended(): void {
159+
$config = [
160+
'service_config' => [
161+
'__version' => 1,
162+
'display_name' => 'Mock Data Source',
163+
'endpoint' => 'http://example.com/data?existing=true',
164+
'auth' => [
165+
'type' => 'api-key',
166+
'add_to' => 'queryparams',
167+
'key' => 'api_key',
168+
'value' => 'test-api-key',
169+
],
170+
],
171+
];
172+
$this->http_data_source = MockDataSource::create( $config );
173+
174+
$this->assertNotInstanceOf( WP_Error::class, $this->http_data_source );
175+
$endpoint = $this->http_data_source->get_endpoint();
176+
$this->assertSame( 'http://example.com/data?existing=true&api_key=test-api-key', $endpoint );
177+
}
178+
179+
public function testNoAuthLeavesConfigUnchanged(): void {
180+
$config = [
181+
'service_config' => [
182+
'__version' => 1,
183+
'display_name' => 'Mock Data Source',
184+
'endpoint' => 'http://example.com/data',
185+
'request_headers' => [ 'X-Custom' => 'value' ],
186+
],
187+
];
188+
$this->http_data_source = MockDataSource::create( $config );
189+
190+
$this->assertNotInstanceOf( WP_Error::class, $this->http_data_source );
191+
$headers = $this->http_data_source->get_request_headers();
192+
$endpoint = $this->http_data_source->get_endpoint();
193+
194+
$this->assertIsArray( $headers );
195+
$this->assertSame( [ 'X-Custom' => 'value' ], $headers );
196+
$this->assertSame( 'http://example.com/data', $endpoint );
197+
}
198+
199+
public function testExistingHeadersAreMergedWithAuthHeaders(): void {
200+
$config = [
201+
'service_config' => [
202+
'__version' => 1,
203+
'display_name' => 'Mock Data Source',
204+
'endpoint' => 'http://example.com',
205+
'request_headers' => [ 'X-Custom' => 'value' ],
206+
'auth' => [
207+
'type' => 'bearer',
208+
'value' => 'test-token',
209+
],
210+
],
211+
];
212+
$this->http_data_source = MockDataSource::create( $config );
213+
214+
$this->assertNotInstanceOf( WP_Error::class, $this->http_data_source );
215+
$headers = $this->http_data_source->get_request_headers();
216+
$this->assertIsArray( $headers );
217+
$this->assertSame(
218+
[
219+
'X-Custom' => 'value',
220+
'Authorization' => 'Bearer test-token',
221+
],
222+
$headers
223+
);
224+
}
70225
}

0 commit comments

Comments
 (0)