Local Storage Binding: List Operation Give Full Paths, Get Operation Expects Relative Paths
In what area(s)?
/area runtime
What version of Dapr?
- Dapr Version: 1.15.6
- OS: Linux
- Component:
bindings.localstorage - Component Version: v1
Expected Behavior
When using a curl commands to query a local storage binding, I would expect I could use the output of the list operation with the get operation.
Actual Behavior
When doing the above, the output of the list operation includes the full path to the file(s) on the local filesystem, but the get operation expects a relative path relative to the rootPath property in the component's YAML file.
Steps to Reproduce the Problem
Dapr Local Storage Binding Path Inconsistency - Reproduction Steps
Prerequisites
- Dapr CLI installed
- Docker installed (for Dapr runtime)
Step 1: Setup Dapr Component
Create a localstorage.yaml file:
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: localstorage
spec:
type: bindings.localstorage
version: v1
metadata:
- name: rootPath
value: "/tmp/dapr-storage"
Step 2: Create Storage Directory
mkdir -p /tmp/dapr-storage/documents
Step 3: Start Dapr Runtime
# Start Dapr with the component
dapr run --app-id test-app --dapr-http-port 3500 --components-path . --app-port 8080 -- sleep 300
Note: The sleep 300 keeps the runtime alive for 5 minutes to run tests.
Step 4: Create Test Files via Dapr Binding
Create first test file:
curl -X POST "http://localhost:3500/v1.0/bindings/localstorage" \
-H "Content-Type: application/json" \
-d '{
"operation": "create",
"metadata": {
"fileName": "documents/test1.json"
},
"data": "{\"id\": \"1\", \"content\": \"Test document 1\"}"
}'
Create second test file:
curl -X POST "http://localhost:3500/v1.0/bindings/localstorage" \
-H "Content-Type: application/json" \
-d '{
"operation": "create",
"metadata": {
"fileName": "documents/test2.json"
},
"data": "{\"id\": \"2\", \"content\": \"Test document 2\"}"
}'
Create file in root directory:
curl -X POST "http://localhost:3500/v1.0/bindings/localstorage" \
-H "Content-Type: application/json" \
-d '{
"operation": "create",
"metadata": {
"fileName": "root-file.txt"
},
"data": "This is a root level file"
}'
Step 5: Verify Files Were Created
# Check filesystem directly
ls -la /tmp/dapr-storage/
ls -la /tmp/dapr-storage/documents/
Expected output:
/tmp/dapr-storage/
├── documents/
│ ├── test1.json
│ └── test2.json
└── root-file.txt
Step 6: List Files via Dapr (Shows the Bug)
List all files:
curl -X POST "http://localhost:3500/v1.0/bindings/localstorage" \
-H "Content-Type: application/json" \
-d '{
"operation": "list",
"metadata": {
"fileName": "",
"prefix": ""
}
}'
Expected Result: Relative paths like ["documents/test1.json", "documents/test2.json", "root-file.txt"]
Actual Result: Absolute paths like ["/tmp/dapr-storage/documents/test1.json", "/tmp/dapr-storage/documents/test2.json", "/tmp/dapr-storage/root-file.txt"]
List files with prefix:
curl -X POST "http://localhost:3500/v1.0/bindings/localstorage" \
-H "Content-Type: application/json" \
-d '{
"operation": "list",
"metadata": {
"fileName": "documents/",
"prefix": "documents/"
}
}'
Expected Result: ["documents/test1.json", "documents/test2.json"]
Actual Result: ["/tmp/dapr-storage/documents/test1.json", "/tmp/dapr-storage/documents/test2.json"]
Step 7: Demonstrate Get Operation Inconsistency
Try to get file using absolute path (from list result) - FAILS:
curl -X POST "http://localhost:3500/v1.0/bindings/localstorage" \
-H "Content-Type: application/json" \
-d '{
"operation": "get",
"metadata": {
"fileName": "/tmp/dapr-storage/documents/test1.json"
}
}'
Result: Error or no data returned
Get file using relative path - WORKS:
curl -X POST "http://localhost:3500/v1.0/bindings/localstorage" \
-H "Content-Type: application/json" \
-d '{
"operation": "get",
"metadata": {
"fileName": "documents/test1.json"
}
}'
Result: Successfully returns {"id": "1", "content": "Test document 1"}
Get root file using relative path - WORKS:
curl -X POST "http://localhost:3500/v1.0/bindings/localstorage" \
-H "Content-Type: application/json" \
-d '{
"operation": "get",
"metadata": {
"fileName": "root-file.txt"
}
}'
Result: Successfully returns This is a root level file
The Problem
- List operation returns absolute paths that include the
rootPathprefix - Get operation expects relative paths from the
rootPath - Result: You cannot directly use the file paths returned by
listin agetoperation
This breaks the abstraction because:
- Application code needs to know about the storage binding's
rootPathconfiguration - Code needs to strip the absolute path prefix to make files accessible
- Different storage bindings might behave differently, making code non-portable
Expected Behavior
The list operation should return relative paths consistent with what the get operation expects:
listshould return:["documents/test1.json", "documents/test2.json", "root-file.txt"]getshould accept:"documents/test1.json"(same format)
Cleanup
# Stop Dapr
# (Ctrl+C in the terminal where you ran dapr run)
# Clean up test files
rm -rf /tmp/dapr-storage
Release Note
RELEASE NOTE: FIX Aligned the output of the list operation with the expected input of the get operation for the localstorage binding.
I opened this up in the wrong repo - but here's the original report: https://github.com/dapr/dapr/issues/8869
This issue has been automatically marked as stale because it has not had activity in the last 30 days. It will be closed in the next 7 days unless it is tagged (pinned, good first issue, help wanted or triaged/resolved) or other activity occurs. Thank you for your contributions.
commenting so it doesn't go stale.