Skip to content

Commit

Permalink
Merge pull request #17711 from ckeditor/ck/15693
Browse files Browse the repository at this point in the history
Feature (upload): It should now be possible to pass the callback to the SimpleUploadConfig#headers property. Closes #15693
  • Loading branch information
Mati365 authored Jan 3, 2025
2 parents 4896a62 + 5b2d270 commit 4517b1c
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,11 @@ class Adapter implements UploadAdapter {
*/
private _sendRequest( file: File ): void {
// Set headers if specified.
const headers = this.options.headers || {};
let headers = this.options.headers || {};

if ( typeof headers === 'function' ) {
headers = headers( file );
}

// Use the withCredentials flag if specified.
const withCredentials = this.options.withCredentials || false;
Expand Down
21 changes: 15 additions & 6 deletions packages/ckeditor5-upload/src/uploadconfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,29 +44,38 @@ export interface SimpleUploadConfig {
uploadUrl: string;

/**
* An object that defines additional [headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers) sent with
* the request to the server during the upload. This is the right place to implement security mechanisms like
* authentication and [CSRF](https://developer.mozilla.org/en-US/docs/Glossary/CSRF) protection.
* [Headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers) sent with the request to the server during the upload.
* This is the right place to implement security mechanisms like authentication and
* [CSRF](https://developer.mozilla.org/en-US/docs/Glossary/CSRF) protection.
*
* The value can be specified either as an object of key-value pairs or a callback function that returns such an object:
*
* ```ts
* ClassicEditor
* .create( editorElement, {
* simpleUpload: {
* // Set headers statically:
* headers: {
* 'X-CSRF-TOKEN': 'CSRF-Token',
* Authorization: 'Bearer <JSON Web Token>'
* }
*
* // Or dynamically, based on the file:
* headers: ( file ) => {
* return {
* 'X-File-Name': file.name,
* 'X-File-Size': file.size
* };
* }
* }
* } );
* .then( ... )
* .catch( ... );
* ```
*
* Learn more about the server application requirements in the
* {@glink features/images/image-upload/simple-upload-adapter#server-side-configuration "Server-side configuration"} section
* of the feature guide.
*/
headers?: Record<string, string>;
headers?: Record<string, string> | ( ( file: File ) => Record<string, string> );

/**
* This flag enables the
Expand Down
50 changes: 50 additions & 0 deletions packages/ckeditor5-upload/tests/adapters/simpleuploadadapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,56 @@ describe( 'SimpleUploadAdapter', () => {
} );
} );

it( 'should use config#headers in the request (when specified as a function)', () => {
const editorElement = document.createElement( 'div' );
document.body.appendChild( editorElement );

return ClassicTestEditor
.create( editorElement, {
plugins: [ SimpleUploadAdapter ],
simpleUpload: {
uploadUrl: 'http://example.com',
headers: file => ( {
'X-File-Name': file.name,
'X-File-Size': file.size.toString()
} )
}
} )
.then( editor => {
const adapter = editor.plugins.get( FileRepository ).createUploadAdapter( loader );
const validResponse = {
url: 'http://example.com/images/image.jpeg'
};

const uploadPromise = adapter.upload();

return loader.file
.then( () => {
const request = sinonXHR.requests[ 0 ];
request.respond( 200, { 'Content-Type': 'application/json' }, JSON.stringify( validResponse ) );

const requestHeaders = request.requestHeaders;

expect( requestHeaders ).to.be.a( 'object' );
expect( requestHeaders ).to.have.property( 'X-File-Name', 'image.jpeg' );
expect( requestHeaders ).to.have.property( 'X-File-Size', '1024' );

return uploadPromise;
} )
.then( uploadResponse => {
expect( uploadResponse ).to.deep.equal( {
url: 'http://example.com/images/image.jpeg',
urls: {
default: 'http://example.com/images/image.jpeg'
}
} );

editorElement.remove();
} )
.then( () => editor.destroy() );
} );
} );

it( 'should not set #requestHeaders of the request if config#headers is not specified', () => {
const editorElement = document.createElement( 'div' );
document.body.appendChild( editorElement );
Expand Down

0 comments on commit 4517b1c

Please sign in to comment.