Ciao developer,
in questo articolo voglio condividere con te la mia esperienza di sviluppo API con Mulesoft, in particolare sulla definizione della specifica del servizio e la manipolazione del payload, quando lavoriamo con i files.
In questo esempio ho voluto creare una API ad hoc con dei semplici metodi GET per la visualizzazione e download del documento, il metodo POST per l’upload.
Iniziamo nel definire il tipo di oggetto che rappresenta un file, con molta fantasia è denominato file:
types:
UploadMultipleFileType:
properties:
file:
description: The file to be uploaded.
required: true
fileTypes: ['application/pdf']
type: file
Come vedete già RAML ci mette a disposizione il tipo “file”, con eventuali attributi per definire i tipi di file da trattare.
Ora non resta che definire i metodi di esempio:
/download:
get:
responses:
200:
headers:
"Content-Disposition":
type: string
default: "attachment"
body:
application/pdf:
/view:
get:
responses:
200:
headers:
"Content-Disposition":
type: string
default: "inline"
body:
application/pdf:
/upload:
post:
body:
multipart/form-data:
type: UploadMultipleFileType[]
minItems: 1
maxItems: 1
responses:
200:
description: Success
Come vedete, in particolare il metodo POST:/upload si attende in ingresso,nel body della chiamata http un array di un elementi di tipo UploadMultipleFileType. Precedentemente definito.
Interessante, va notata la definizione standard degli headers nei metodi GET.
Come facciamo a impostare tali valori nell’implementazione del servizio? Molto semplice 🙂 basta aggiungere l’header Content-Disposition nella variabile outboundHeaders mediante uno statement set-variable, in questo modo:
import mergeWith from dw::core::Objects
output application/java
---
vars.outboundHeaders mergeWith {
'Content-Disposition': 'attachment; filename="$(attributes.fileName)"'
}
Analogamente per la versione “inline” (mergeWith per non sovrascrivere l’intero contenuto della variabile)
Siamo arrivati al metodo interessante, quello di upload per leggere e salvare il file nel server. Considerando che il payload è un insieme di “parti” noi andremo a selezionare un “parte” denominata “file” come specificato nel servizio:
payload.parts.file.content
E’ possibile accedere agli attributi del file mediante gli headers, come per esempio il nome del file:
payload.parts.file.headers["Content-Disposition"]
Nel sorgente di esempio, nello statement che precede il salvataggio del file, ho inserito un transform message che converte il payload in un oggetto Java, posizionandosi con il debug possiamo vedere la forma del nostro payload come segue:
Infine, per simulare le chiamate mediante una web app ho creato una semplice pagina html con le varie azioni, raggiungibile alla URL: http://localhost:8081/api/index
Chiaramente questo codice non è sufficiente per implementare tutta la logica applicativa che sta dietro al contesto di questo tipo di applicazioni ma, spero sia d’aiuto come spunto.
Al seguente URL potete scaricare il codice di esempio:
https://bitbucket.org/Bonny/multipart-api-example.git
Leggi anche: I love Liquibase