Enhance IUCN API integration: Add support for v4 API, improve error handling, and clarify authentication instructions in README.
Replit-Commit-Author: Agent Replit-Commit-Session-Id: e931b5ab-041b-42e7-baf1-50017869cef6 Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/e19c6a51-7e4c-4bb8-a6a6-46dc00f0ec99/fe2c55e5-ba3a-4d5e-84f0-b14bbe529292.jpg
This commit is contained in:
39
README.md
39
README.md
@ -61,10 +61,22 @@ The application requires a CITES+ API token for authentication. To obtain a toke
|
|||||||
4. Enter the token in the application's authentication panel
|
4. Enter the token in the application's authentication panel
|
||||||
|
|
||||||
### IUCN Red List API
|
### IUCN Red List API
|
||||||
The application requires an IUCN Red List API key for accessing conservation data. To obtain a key:
|
The application supports both IUCN Red List API v3 and v4 versions:
|
||||||
|
|
||||||
|
#### IUCN API v3 (Legacy)
|
||||||
|
To use the v3 API:
|
||||||
1. Visit [https://apiv3.iucnredlist.org/api/v3/docs](https://apiv3.iucnredlist.org/api/v3/docs)
|
1. Visit [https://apiv3.iucnredlist.org/api/v3/docs](https://apiv3.iucnredlist.org/api/v3/docs)
|
||||||
2. Register for an account and request an API key
|
2. Register for an account and request an API key
|
||||||
3. The key will be automatically configured in the application's environment variables
|
3. The key will be automatically configured in the application's environment variables (`IUCN_API_KEY`)
|
||||||
|
|
||||||
|
#### IUCN API v4 (Recommended)
|
||||||
|
For enhanced functionality with the v4 API:
|
||||||
|
1. Visit [https://apiv3.iucnredlist.org/api/v4/docs](https://apiv3.iucnredlist.org/api/v4/docs)
|
||||||
|
2. Register for an account and request access to the v4 API
|
||||||
|
3. Generate a bearer token for the v4 API
|
||||||
|
4. Enter the token in the application's authentication panel (IUCN tab)
|
||||||
|
|
||||||
|
The application will intelligently use v4 if available, with automatic fallback to v3 when needed.
|
||||||
|
|
||||||
## Getting Started
|
## Getting Started
|
||||||
|
|
||||||
@ -101,8 +113,10 @@ The application requires an IUCN Red List API key for accessing conservation dat
|
|||||||
### Using the Application
|
### Using the Application
|
||||||
|
|
||||||
1. **API Authentication**:
|
1. **API Authentication**:
|
||||||
- Enter your CITES+ API token in the authentication panel
|
- Click the "API Token" button to open the authentication panel
|
||||||
- The API status indicators will show if both APIs are successfully connected
|
- In the CITES tab, enter your CITES+ API token
|
||||||
|
- In the IUCN tab, enter your IUCN v4 bearer token (if available)
|
||||||
|
- The API status indicators will show if both APIs are successfully connected, including which version of the IUCN API is active
|
||||||
|
|
||||||
2. **Searching for Species**:
|
2. **Searching for Species**:
|
||||||
- Enter a scientific name (e.g., "Panthera tigris") in the search box
|
- Enter a scientific name (e.g., "Panthera tigris") in the search box
|
||||||
@ -180,9 +194,24 @@ npm test
|
|||||||
|
|
||||||
## Limitations and Known Issues
|
## Limitations and Known Issues
|
||||||
|
|
||||||
- IUCN API may return 414 errors for very long scientific names
|
|
||||||
- Some species may not have data in all API sources
|
- Some species may not have data in all API sources
|
||||||
- API rate limits may apply (refer to API documentation for details)
|
- API rate limits may apply (refer to API documentation for details)
|
||||||
|
- IUCN API v3 may return 414 errors for very long scientific names (this is minimized in the implementation)
|
||||||
|
- IUCN API v4 requires a separate bearer token authentication
|
||||||
|
|
||||||
|
## API Version Handling
|
||||||
|
|
||||||
|
The application intelligently manages API versions with the following approach:
|
||||||
|
|
||||||
|
- **IUCN API Version Selection**:
|
||||||
|
- The system first attempts to use IUCN API v4 if a bearer token is available
|
||||||
|
- If v4 returns an error or isn't available, the system automatically falls back to v3
|
||||||
|
- All API responses include an `apiVersion` field indicating which version was used
|
||||||
|
|
||||||
|
- **Version-Specific Authentication**:
|
||||||
|
- CITES+ API: Uses a token-based authentication via query parameter
|
||||||
|
- IUCN v3: Uses an API key via environment variable and query parameter
|
||||||
|
- IUCN v4: Uses OAuth 2.0 Bearer token authentication via headers
|
||||||
|
|
||||||
## Future Enhancements
|
## Future Enhancements
|
||||||
|
|
||||||
|
@ -75,12 +75,12 @@ export default function ApiStatus({ citesToken }: ApiStatusProps) {
|
|||||||
</Badge>
|
</Badge>
|
||||||
</div>
|
</div>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipContent side="bottom">
|
<TooltipContent side="bottom" className="max-w-md">
|
||||||
{citesStatus === 'connected'
|
{citesStatus === 'connected'
|
||||||
? 'CITES+ API is connected and working'
|
? 'CITES+ API is connected and working'
|
||||||
: citesStatus === 'checking'
|
: citesStatus === 'checking'
|
||||||
? 'Checking CITES+ API connection...'
|
? 'Checking CITES+ API connection...'
|
||||||
: citesApiData?.message || 'CITES+ API is not connected. Please add your API token.'}
|
: citesApiData?.message || 'CITES+ API is not connected. Click "API Token" and add your CITES+ API token.'}
|
||||||
</TooltipContent>
|
</TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</TooltipProvider>
|
</TooltipProvider>
|
||||||
@ -101,12 +101,12 @@ export default function ApiStatus({ citesToken }: ApiStatusProps) {
|
|||||||
</Badge>
|
</Badge>
|
||||||
</div>
|
</div>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipContent side="bottom">
|
<TooltipContent side="bottom" className="max-w-md">
|
||||||
{iucnStatus === 'connected'
|
{iucnStatus === 'connected'
|
||||||
? `IUCN Red List API ${iucnApiVersion} is connected and working`
|
? `IUCN Red List API ${iucnApiVersion} is connected and working`
|
||||||
: iucnStatus === 'checking'
|
: iucnStatus === 'checking'
|
||||||
? 'Checking IUCN Red List API connection...'
|
? 'Checking IUCN Red List API connection...'
|
||||||
: iucnApiData?.message || 'IUCN Red List API connection issue. Check the API key.'}
|
: iucnApiData?.message || 'IUCN Red List API connection issue. To use IUCN API features, click "API Token" and add your API key on the IUCN tab.'}
|
||||||
</TooltipContent>
|
</TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</TooltipProvider>
|
</TooltipProvider>
|
||||||
|
@ -291,10 +291,10 @@ export async function registerRoutes(app: Express): Promise<Server> {
|
|||||||
// Try V4 API first (with bearer token)
|
// Try V4 API first (with bearer token)
|
||||||
const activeToken = await storage.getActiveToken();
|
const activeToken = await storage.getActiveToken();
|
||||||
if (activeToken?.iucnToken) {
|
if (activeToken?.iucnToken) {
|
||||||
// Use the version endpoint which is the simplest endpoint
|
|
||||||
const versionUrl = `${IUCN_V4_BASE_URL}/version`;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// Use a simpler endpoint to check if the API is working - we'll just ping the version endpoint
|
||||||
|
const versionUrl = `${IUCN_V4_BASE_URL}/version`;
|
||||||
|
|
||||||
const response = await axios.get(versionUrl, {
|
const response = await axios.get(versionUrl, {
|
||||||
headers: {
|
headers: {
|
||||||
"Authorization": `Bearer ${activeToken.iucnToken}`
|
"Authorization": `Bearer ${activeToken.iucnToken}`
|
||||||
@ -308,46 +308,61 @@ export async function registerRoutes(app: Express): Promise<Server> {
|
|||||||
message: "IUCN API v4 is connected and responding"
|
message: "IUCN API v4 is connected and responding"
|
||||||
});
|
});
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
// If V4 fails, fall back to checking V3 with environment API key
|
console.log("IUCN V4 API check failed:", error.message);
|
||||||
console.log("IUCN V4 API check failed, falling back to V3:", error.message);
|
|
||||||
|
// If token is invalid, return a useful message
|
||||||
|
if (error.response?.status === 401) {
|
||||||
|
return res.status(401).json({
|
||||||
|
success: false,
|
||||||
|
connected: false,
|
||||||
|
message: "IUCN API v4 token is invalid. Please check your token and try again."
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// For other errors, continue to try v3
|
||||||
|
console.log("Falling back to IUCN v3 API check");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fallback to V3 API (with query parameter token)
|
// If no v4 token or v4 check failed, try v3
|
||||||
const apiKey = process.env.IUCN_API_KEY;
|
const apiKey = process.env.IUCN_API_KEY;
|
||||||
if (!apiKey) {
|
if (!apiKey) {
|
||||||
return res.status(401).json({
|
return res.status(401).json({
|
||||||
success: false,
|
success: false,
|
||||||
connected: false,
|
connected: false,
|
||||||
message: "IUCN API key is not configured"
|
message: "No IUCN API credentials found. Please add your IUCN API key."
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use the version endpoint for V3
|
|
||||||
const versionUrl = `${IUCN_V3_BASE_URL}/version`;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Make sure we're not including any parameters in the URL itself - only in params object
|
// For v3, use a really simple request to avoid the 414 error
|
||||||
const response = await axios.get(versionUrl, {
|
const response = await axios.get(`${IUCN_V3_BASE_URL}/version`, {
|
||||||
params: { token: apiKey }
|
params: { token: apiKey }
|
||||||
});
|
});
|
||||||
|
|
||||||
res.json({
|
return res.json({
|
||||||
success: true,
|
success: true,
|
||||||
connected: true,
|
connected: true,
|
||||||
apiVersion: "v3",
|
apiVersion: "v3",
|
||||||
message: "IUCN API v3 is connected and responding"
|
message: "IUCN API v3 is connected and responding"
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error: any) {
|
||||||
if (axios.isAxiosError(error) && error.response) {
|
// Handle v3 API errors
|
||||||
return res.status(error.response.status).json({
|
console.log("IUCN V3 API check failed:", error.message);
|
||||||
|
|
||||||
|
if (error.response?.status === 401) {
|
||||||
|
return res.status(401).json({
|
||||||
success: false,
|
success: false,
|
||||||
connected: false,
|
connected: false,
|
||||||
message: "Failed to connect to IUCN API: " + (error.response?.data?.message || error.message),
|
message: "IUCN API v3 key is invalid. Please check your environment variables."
|
||||||
status: error.response.status
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
throw error;
|
|
||||||
|
return res.status(error.response?.status || 500).json({
|
||||||
|
success: false,
|
||||||
|
connected: false,
|
||||||
|
message: "Failed to connect to IUCN API: " + (error.response?.data?.message || error.message)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const errorMessage = error instanceof Error ? error.message : String(error);
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
||||||
|
Reference in New Issue
Block a user