OData Cheat Sheet (CAP): Unterschied zwischen den Versionen

Aus MattWiki
(Die Seite wurde neu angelegt: „This article holds notes on how to quickly get certain responses from a OData serivce. Source: https://www.odata.org/getting-started/basic-tutorial/ == OData V4 == === Querying Data === <code>GET serviceRoot/People?$count=true</code> Returns the number of records retreived Kategorie:Development“)
 
Keine Bearbeitungszusammenfassung
 
(3 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
Zeile 1: Zeile 1:
This article holds notes on how to quickly get certain responses from a OData serivce.
This article holds notes on how to quickly get certain responses from a OData service. However, it is specifically based on a SAP Cloud Application Programming Model (CAP) OData service.


Source: https://www.odata.org/getting-started/basic-tutorial/
Sources for OData in general: https://www.odata.org/getting-started/basic-tutorial/


For more informations on CAP see: [[SAP Cloud Application Programming Model Getting Started (CAP)]]
== OData V4 ==
== OData V4 ==


Zeile 9: Zeile 10:


Returns the number of records retreived
Returns the number of records retreived
== Accessing OData Services from Command Line ==
For further details on OData Services see [[OData Cheat Sheet (CAP)]]
=== Examples for OData V4 Get Requests via URL ===
The following table shows examples of what can be requested with a given url.
{| class="wikitable"
!What
!URL
|-
|Bookshop service root
|http://localhost:4004/odata/v4/bookshop
|-
|Bookshop service, all Books entities
|http://localhost:4004/odata/v4/bookshop/Books
|-
|Bookshop service, Books entity with specified key ID in parentheses
|http://localhost:4004/odata/v4/bookshop/Books(3b1e1d9e-9563-4cd3-a448-69b8b8f1c384)<nowiki/>http://localhost:4004/odata/v4/bookshop/Books/3b1e1d9e-9563-4cd3-a448-69b8b8f1c384
|-
|Bookshop service, Books entity with filter on title field
|http://localhost:4004/odata/v4/bookshop/Books?$filter=contains(title,%27The%20Player%20Of%20Games%27)
|-
|Bookshop service, value from field title from Books entity with key ID in parentheses
|http://localhost:4004/odata/v4/bookshop/Books(3b1e1d9e-9563-4cd3-a448-69b8b8f1c384)/title
|-
|Unbound totalStock function from Bookshop service
|http://localhost:4004/odata/v4/bookshop/totalStock()
|-
|Bound stockValue function from Books entity in Bookshop service
|http://localhost:4004/odata/v4/bookshop/Books/3b1e1d9e-9563-4cd3-a448-69b8b8f1c384/stockValue()
|}
=== Reading from Services ===
Read output of services via ''curl'' and pipe it through ''jq'' for nicer formatting:
curl -s 'localhost:4004/odata/v4/bookshop/Orders' | jq
Output (example for Bookshop repo):<syntaxhighlight lang="json" line="1">
{
  "@odata.context": "$metadata#Orders",
  "value": [
    {
      "ID": "6091d4ab-650e-4afa-90bb-163305e473a2",
      "comment": "second order"
    },
    {
      "ID": "ac5aeb9f-c7cd-4f52-ab4a-9c0313ded402",
      "comment": "first order"
    }
  ]
}
</syntaxhighlight>
=== Reading Unbound Functions from Services ===
Read output of a unbound function via ''curl'' and pipe it through ''jq'' for nicer formatting:
curl -s 'localhost:4004/odata/v4/bookshop/totalStock()' | jq
Output:<syntaxhighlight lang="json" line="1">
{
  "@odata.context": "$metadata#Edm.Int32",
  "value": 147
}
</syntaxhighlight>
=== Reading Record with Key from Service ===
Read output of one particular record from a service via ''curl'' and pipe it through ''jq'' for nicer formatting:
curl -s 'localhost:4004/odata/v4/bookshop/Orders/6091d4ab-650e-4afa-90bb-163305e473a2' | jq
curl -s 'localhost:4004/odata/v4/bookshop/Orders(6091d4ab-650e-4afa-90bb-163305e473a2) | jq
Output (example for Bookshop repo):<syntaxhighlight lang="json" line="1">
{
  "@odata.context": "$metadata#Orders/$entity",
  "ID": "6091d4ab-650e-4afa-90bb-163305e473a2",
  "comment": "second order"
}
</syntaxhighlight>
=== Reading Bound Functions from Service ===
Read output of a function bound to a service entity while providing a key ID:
curl -s 'localhost:4004/odata/v4/bookshop/Books/3b1e1d9e-9563-4cd3-a448-69b8b8f1c384/stockValue()' | jq
Output:<syntaxhighlight lang="json" line="1">
{
  "@odata.context": "../$metadata#Edm.Int32",
  "value": 42
}
</syntaxhighlight>
=== Reading from Services while returning Request Header ===
curl -is 'localhost:4004/odata/v4/bookshop/Orders'
Output:<syntaxhighlight lang="http" line="1">
HTTP/1.1 200 OK
X-Powered-By: Express
X-Correlation-ID: c8dbb1e1-6124-473f-b482-4efe091d1f5b
OData-Version: 4.0
content-type: application/json;odata.metadata=minimal
Date: Sat, 22 Jun 2024 14:57:24 GMT
Connection: keep-alive
Keep-Alive: timeout=5
Content-Length: 491
{"@odata.context":"$metadata#Books","value":[{"ID":"3b1e1d9e-9563-4cd3-a448-69b8b8f1c384","title":"The Player Of Games","author_ID":"d5adee57-ef4a-441e-bfa7-9acac6e647e4","stock":5},{"ID":"dc3c659f-29c5-4b21-b3b0-44c58bae5306","title":"The Hitch Hiker's Guide To The Galaxy","author_ID":"01afafdf-0b4a-475b-b107-77fd3c9157da","stock":42},{"ID":"f584c9c9-c076-423a-9638-4c5917a4cbac","title":"Mostly Harmless","author_ID":"01afafdf-0b4a-475b-b107-77fd3c9157da","stock":100,"urgency":"HIGH"}]}
</syntaxhighlight>
=== Continuous Reading from Services after File Change ===
This section is not specitic to CAP, but in design time it perhaps helps to reload for example the read services from the section before after changing the source code.
ls srv/* | entr -c bash -c 'curl -s localhost:4004/odata/v4/bookshop/Orders | jq .'
<code>entr</code> is a tool which looks for file changes on a list of supplemended files and executes a command. So <code>ls srv/*</code> supplements a file list and pipes it to <code>entr</code> which in turn executes the bash command <code>curl</code> to query the OData service. The result here would be for example the following one after every change to a file in the ''srv'' subdirectory:<syntaxhighlight lang="json" line="1">
{
  "@odata.context": "$metadata#Orders",
  "value": [
    {
      "ID": "6091d4ab-650e-4afa-90bb-163305e473a2",
      "comment": "second order"
    },
    {
      "ID": "ac5aeb9f-c7cd-4f52-ab4a-9c0313ded402",
      "comment": "first order"
    }
  ]
}
</syntaxhighlight>'''Remarks:''' When saving a file in the ''srv'' subdirectory and when using <code>cds watch</code> is used this will trigger a restart of the CDS server. As this takes some time the <code>entr</code> command could trigger the <code>curl</code> command before the CDS server has fully restarted. A possible solution to solve this issue is described below in section ''Custom Application Logic Within CAP'', sub section ''Custom Server''.
'''Hint:''' Check out the more robust CAP listening plugin from Qmacro: https://github.com/qmacro/cap-listening-plugin
=== Deep Insert into Service with POST ===
For performing a deep insert we first need a at least two level deep structure.
The following ''neworder.json'' file with a two-level deep structure is given:<syntaxhighlight lang="json" line="1">
{
    "comment": "New Order",
    "Items": [
            {
                "pos": 1,
                "quantity": 10
            },
            {
                "pos": 2,
                "quantity": 20
            }
        ]
}
</syntaxhighlight>To perform the deep insert put the json file into the service by utilizing ''curl''. The filename needs to be prefixed with a @. As we are connecting to a web service we also need to add a header and specify the content type, in this case ''application/json'':
curl --verbose --data @neworder.json --header 'content-type: application/json' --url 'localhost:4004/odata/v4/bookshop/Orders'
By default ''curl'' with parameter ''--data'' uses the POST method. For more details on the HTTP methods see [[Notable RFCs#HTTP Methods GET, POST, PUT, DELETE|Notable RFCs Section HTTP Methods GET, POST, PUT, DELETE]]
We should receive an answer that is similar to the following one in that we are connected to localhost, and we posted to odata service and that the HTTP code was ''201 Created:''<syntaxhighlight lang="http">
*  Trying 127.0.0.1:4004...
* Connected to localhost (127.0.0.1) port 4004 (#0)
> POST /odata/v4/bookshop/Orders HTTP/1.1
> Host: localhost:4004
> User-Agent: curl/7.74.0
> Accept: */*
> content-type: application/json
> Content-Length: 193
>
* upload completely sent off: 193 out of 193 bytes
* Mark bundle as not supporting multiuse
< HTTP/1.1 201 Created
< X-Powered-By: Express
< X-Correlation-ID: 4eee1d5a-5b43-4577-8257-a99b026a0c43
< OData-Version: 4.0
< content-type: application/json;odata.metadata=minimal
< Location: Orders(9416b371-2355-402a-b06d-34f5b2c61704)
< Date: Sat, 20 Apr 2024 12:23:52 GMT
< Connection: keep-alive
< Keep-Alive: timeout=5
< Content-Length: 280
<
* Connection #0 to host localhost left intact
{"@odata.context":"$metadata#Orders(Items())/$entity","ID":"9416b371-2355-402a-b06d-34f5b2c61704","comment":"New Order","Items":[{"parent_ID":"9416b371-2355-402a-b06d-34f5b2c61704","pos":1,"quantity":10},{"parent_ID":"9416b371-2355-402a-b06d-34f5b2c61704","pos":2,"quantity":20}]}
</syntaxhighlight>
=== Update Records via Service with PATCH ===
Following up the deep insert example above let's assume we want to update the Order with comment ''New Order''. For this we create a ''neworder-update.json'' with a different content, i.e.:<syntaxhighlight lang="json" line="1">
{
  "comment": "New Order",
  "Items": [
          {
              "pos": 1,
              "quantity": 1000
          }
      ]
}
</syntaxhighlight>To perform the update we need to refer to the ID of the previously created Order to have this one updated. This happens by using the ID ''9416b371-2355-402a-b06d-34f5b2c61704'' from the server response above and adding it to the url after ''Order'' in parentheses:
curl -X PATCH --verbose --data @neworder-update.json --header 'content-type: application/json' --url 'localhost:4004/odata/v4/bookshop/Orders(9416b371-2355-402a-b06d-34f5b2c61704)' | jq .
The expected result is HTTP code ''200 OK'':<syntaxhighlight lang="http">
  % Total    % Received % Xferd  Average Speed  Time    Time    Time  Current
                                Dload  Upload  Total  Spent    Left  Speed
  0    0    0    0    0    0      0      0 --:--:-- --:--:-- --:--:--    0*  Trying 127.0.0.1:4004...
* Connected to localhost (127.0.0.1) port 4004 (#0)
> PATCH /odata/v4/bookshop/Orders(9416b371-2355-402a-b06d-34f5b2c61704) HTTP/1.1
> Host: localhost:4004
> User-Agent: curl/7.74.0
> Accept: */*
> content-type: application/json
> Content-Length: 121
>
} [121 bytes data]
* upload completely sent off: 121 out of 121 bytes
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< X-Powered-By: Express
< X-Correlation-ID: 9a21bb8f-cfcc-4641-bc68-2f1bcbb7d5a8
< OData-Version: 4.0
< content-type: application/json;odata.metadata=minimal
< Date: Sat, 20 Apr 2024 12:34:13 GMT
< Connection: keep-alive
< Keep-Alive: timeout=5
< Content-Length: 198
<
{ [198 bytes data]
100  319  100  198  100  121  19800  12100 --:--:-- --:--:-- --:--:-- 31900
* Connection #0 to host localhost left intact
{
  "@odata.context": "$metadata#Orders/$entity",
  "ID": "9416b371-2355-402a-b06d-34f5b2c61704",
  "comment": "New Order",
  "Items": [
    {
      "parent_ID": "9416b371-2355-402a-b06d-34f5b2c61704",
      "pos": 1,
      "quantity": 1000
    }
  ]
}
</syntaxhighlight>Check the results with queueing the service again:
curl -s 'localhost:4004/odata/v4/bookshop/Orders?$expand=Items' | jq
<syntaxhighlight lang="json">
{
  "@odata.context": "$metadata#Orders(Items())",
  "value": [
    {
      ...
    },
    {
      "ID": "9416b371-2355-402a-b06d-34f5b2c61704",
      "comment": "New Order",
      "Items": [
        {
          "parent_ID": "9416b371-2355-402a-b06d-34f5b2c61704",
          "pos": 1,
          "quantity": 1000
        }
      ]
    },
    {
      ...
    }
  ]
}
</syntaxhighlight>
== OData Service Request Contents ==
Below are contents of request ''req'' from actions listed
{| class="wikitable"
!Object
!Response
!Comment
|-
|req.target
|bookshop_Books
|returns req.target.name
|-
|req.params
|(1) ['3b1e1d9e-9563-4cd3-a448-69b8b8f1c384']
|returns an array of length 1
|-
|req.params[0]
|'3b1e1d9e-9563-4cd3-a448-69b8b8f1c384'
|returns first element of the params array
|}
[[Kategorie:Development]]
[[Kategorie:Development]]
[[Kategorie:SAP]]

Aktuelle Version vom 13. Juli 2024, 14:38 Uhr

This article holds notes on how to quickly get certain responses from a OData service. However, it is specifically based on a SAP Cloud Application Programming Model (CAP) OData service.

Sources for OData in general: https://www.odata.org/getting-started/basic-tutorial/

For more informations on CAP see: SAP Cloud Application Programming Model Getting Started (CAP)

OData V4

Querying Data

GET serviceRoot/People?$count=true

Returns the number of records retreived

Accessing OData Services from Command Line

For further details on OData Services see OData Cheat Sheet (CAP)

Examples for OData V4 Get Requests via URL

The following table shows examples of what can be requested with a given url.

What URL
Bookshop service root http://localhost:4004/odata/v4/bookshop
Bookshop service, all Books entities http://localhost:4004/odata/v4/bookshop/Books
Bookshop service, Books entity with specified key ID in parentheses http://localhost:4004/odata/v4/bookshop/Books(3b1e1d9e-9563-4cd3-a448-69b8b8f1c384)http://localhost:4004/odata/v4/bookshop/Books/3b1e1d9e-9563-4cd3-a448-69b8b8f1c384
Bookshop service, Books entity with filter on title field http://localhost:4004/odata/v4/bookshop/Books?$filter=contains(title,%27The%20Player%20Of%20Games%27)
Bookshop service, value from field title from Books entity with key ID in parentheses http://localhost:4004/odata/v4/bookshop/Books(3b1e1d9e-9563-4cd3-a448-69b8b8f1c384)/title
Unbound totalStock function from Bookshop service http://localhost:4004/odata/v4/bookshop/totalStock()
Bound stockValue function from Books entity in Bookshop service http://localhost:4004/odata/v4/bookshop/Books/3b1e1d9e-9563-4cd3-a448-69b8b8f1c384/stockValue()

Reading from Services

Read output of services via curl and pipe it through jq for nicer formatting:

curl -s 'localhost:4004/odata/v4/bookshop/Orders' | jq

Output (example for Bookshop repo):

{
  "@odata.context": "$metadata#Orders",
  "value": [
    {
      "ID": "6091d4ab-650e-4afa-90bb-163305e473a2",
      "comment": "second order"
    },
    {
      "ID": "ac5aeb9f-c7cd-4f52-ab4a-9c0313ded402",
      "comment": "first order"
    }
  ]
}

Reading Unbound Functions from Services

Read output of a unbound function via curl and pipe it through jq for nicer formatting:

curl -s 'localhost:4004/odata/v4/bookshop/totalStock()' | jq

Output:

{
  "@odata.context": "$metadata#Edm.Int32",
  "value": 147
}

Reading Record with Key from Service

Read output of one particular record from a service via curl and pipe it through jq for nicer formatting:

curl -s 'localhost:4004/odata/v4/bookshop/Orders/6091d4ab-650e-4afa-90bb-163305e473a2' | jq
curl -s 'localhost:4004/odata/v4/bookshop/Orders(6091d4ab-650e-4afa-90bb-163305e473a2) | jq

Output (example for Bookshop repo):

{
  "@odata.context": "$metadata#Orders/$entity",
  "ID": "6091d4ab-650e-4afa-90bb-163305e473a2",
  "comment": "second order"
}

Reading Bound Functions from Service

Read output of a function bound to a service entity while providing a key ID:

curl -s 'localhost:4004/odata/v4/bookshop/Books/3b1e1d9e-9563-4cd3-a448-69b8b8f1c384/stockValue()' | jq

Output:

{
  "@odata.context": "../$metadata#Edm.Int32",
  "value": 42
}

Reading from Services while returning Request Header

curl -is 'localhost:4004/odata/v4/bookshop/Orders'

Output:

HTTP/1.1 200 OK
X-Powered-By: Express
X-Correlation-ID: c8dbb1e1-6124-473f-b482-4efe091d1f5b
OData-Version: 4.0
content-type: application/json;odata.metadata=minimal
Date: Sat, 22 Jun 2024 14:57:24 GMT
Connection: keep-alive
Keep-Alive: timeout=5
Content-Length: 491

{"@odata.context":"$metadata#Books","value":[{"ID":"3b1e1d9e-9563-4cd3-a448-69b8b8f1c384","title":"The Player Of Games","author_ID":"d5adee57-ef4a-441e-bfa7-9acac6e647e4","stock":5},{"ID":"dc3c659f-29c5-4b21-b3b0-44c58bae5306","title":"The Hitch Hiker's Guide To The Galaxy","author_ID":"01afafdf-0b4a-475b-b107-77fd3c9157da","stock":42},{"ID":"f584c9c9-c076-423a-9638-4c5917a4cbac","title":"Mostly Harmless","author_ID":"01afafdf-0b4a-475b-b107-77fd3c9157da","stock":100,"urgency":"HIGH"}]}

Continuous Reading from Services after File Change

This section is not specitic to CAP, but in design time it perhaps helps to reload for example the read services from the section before after changing the source code.

ls srv/* | entr -c bash -c 'curl -s localhost:4004/odata/v4/bookshop/Orders | jq .'

entr is a tool which looks for file changes on a list of supplemended files and executes a command. So ls srv/* supplements a file list and pipes it to entr which in turn executes the bash command curl to query the OData service. The result here would be for example the following one after every change to a file in the srv subdirectory:

{
  "@odata.context": "$metadata#Orders",
  "value": [
    {
      "ID": "6091d4ab-650e-4afa-90bb-163305e473a2",
      "comment": "second order"
    },
    {
      "ID": "ac5aeb9f-c7cd-4f52-ab4a-9c0313ded402",
      "comment": "first order"
    }
  ]
}

Remarks: When saving a file in the srv subdirectory and when using cds watch is used this will trigger a restart of the CDS server. As this takes some time the entr command could trigger the curl command before the CDS server has fully restarted. A possible solution to solve this issue is described below in section Custom Application Logic Within CAP, sub section Custom Server.

Hint: Check out the more robust CAP listening plugin from Qmacro: https://github.com/qmacro/cap-listening-plugin

Deep Insert into Service with POST

For performing a deep insert we first need a at least two level deep structure.

The following neworder.json file with a two-level deep structure is given:

{
    "comment": "New Order",
    "Items": [
            {
                "pos": 1,
                "quantity": 10
            },
            {
                "pos": 2,
                "quantity": 20
            }
        ]
}

To perform the deep insert put the json file into the service by utilizing curl. The filename needs to be prefixed with a @. As we are connecting to a web service we also need to add a header and specify the content type, in this case application/json:

curl --verbose --data @neworder.json --header 'content-type: application/json' --url 'localhost:4004/odata/v4/bookshop/Orders'

By default curl with parameter --data uses the POST method. For more details on the HTTP methods see Notable RFCs Section HTTP Methods GET, POST, PUT, DELETE

We should receive an answer that is similar to the following one in that we are connected to localhost, and we posted to odata service and that the HTTP code was 201 Created:

*   Trying 127.0.0.1:4004...
* Connected to localhost (127.0.0.1) port 4004 (#0)
> POST /odata/v4/bookshop/Orders HTTP/1.1
> Host: localhost:4004
> User-Agent: curl/7.74.0
> Accept: */*
> content-type: application/json
> Content-Length: 193
> 
* upload completely sent off: 193 out of 193 bytes
* Mark bundle as not supporting multiuse
< HTTP/1.1 201 Created
< X-Powered-By: Express
< X-Correlation-ID: 4eee1d5a-5b43-4577-8257-a99b026a0c43
< OData-Version: 4.0
< content-type: application/json;odata.metadata=minimal
< Location: Orders(9416b371-2355-402a-b06d-34f5b2c61704)
< Date: Sat, 20 Apr 2024 12:23:52 GMT
< Connection: keep-alive
< Keep-Alive: timeout=5
< Content-Length: 280
< 
* Connection #0 to host localhost left intact
{"@odata.context":"$metadata#Orders(Items())/$entity","ID":"9416b371-2355-402a-b06d-34f5b2c61704","comment":"New Order","Items":[{"parent_ID":"9416b371-2355-402a-b06d-34f5b2c61704","pos":1,"quantity":10},{"parent_ID":"9416b371-2355-402a-b06d-34f5b2c61704","pos":2,"quantity":20}]}

Update Records via Service with PATCH

Following up the deep insert example above let's assume we want to update the Order with comment New Order. For this we create a neworder-update.json with a different content, i.e.:

{
  "comment": "New Order",
  "Items": [
          {
              "pos": 1,
              "quantity": 1000
          }
      ]
}

To perform the update we need to refer to the ID of the previously created Order to have this one updated. This happens by using the ID 9416b371-2355-402a-b06d-34f5b2c61704 from the server response above and adding it to the url after Order in parentheses:

curl -X PATCH --verbose --data @neworder-update.json --header 'content-type: application/json' --url 'localhost:4004/odata/v4/bookshop/Orders(9416b371-2355-402a-b06d-34f5b2c61704)' | jq .

The expected result is HTTP code 200 OK:

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0*   Trying 127.0.0.1:4004...
* Connected to localhost (127.0.0.1) port 4004 (#0)
> PATCH /odata/v4/bookshop/Orders(9416b371-2355-402a-b06d-34f5b2c61704) HTTP/1.1
> Host: localhost:4004
> User-Agent: curl/7.74.0
> Accept: */*
> content-type: application/json
> Content-Length: 121
> 
} [121 bytes data]
* upload completely sent off: 121 out of 121 bytes
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< X-Powered-By: Express
< X-Correlation-ID: 9a21bb8f-cfcc-4641-bc68-2f1bcbb7d5a8
< OData-Version: 4.0
< content-type: application/json;odata.metadata=minimal
< Date: Sat, 20 Apr 2024 12:34:13 GMT
< Connection: keep-alive
< Keep-Alive: timeout=5
< Content-Length: 198
< 
{ [198 bytes data]
100   319  100   198  100   121  19800  12100 --:--:-- --:--:-- --:--:-- 31900
* Connection #0 to host localhost left intact
{
  "@odata.context": "$metadata#Orders/$entity",
  "ID": "9416b371-2355-402a-b06d-34f5b2c61704",
  "comment": "New Order",
  "Items": [
    {
      "parent_ID": "9416b371-2355-402a-b06d-34f5b2c61704",
      "pos": 1,
      "quantity": 1000
    }
  ]
}

Check the results with queueing the service again:

curl -s 'localhost:4004/odata/v4/bookshop/Orders?$expand=Items' | jq
{
  "@odata.context": "$metadata#Orders(Items())",
  "value": [
    {
      ...
    },
    {
      "ID": "9416b371-2355-402a-b06d-34f5b2c61704",
      "comment": "New Order",
      "Items": [
        {
          "parent_ID": "9416b371-2355-402a-b06d-34f5b2c61704",
          "pos": 1,
          "quantity": 1000
        }
      ]
    },
    {
      ...
    }
  ]
}



OData Service Request Contents

Below are contents of request req from actions listed

Object Response Comment
req.target bookshop_Books returns req.target.name
req.params (1) ['3b1e1d9e-9563-4cd3-a448-69b8b8f1c384'] returns an array of length 1
req.params[0] '3b1e1d9e-9563-4cd3-a448-69b8b8f1c384' returns first element of the params array