-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add recognition of service exception reports
If the WMS or WFS service responds to a GetCapabilities request with a ServiceException report then this will be recognised and the promise rejected with a ServiceExceptionError.
- Loading branch information
Showing
14 changed files
with
370 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<ows:ExceptionReport xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ows="http://www.opengis.net/ows" version="1.1.0" language="en-US" xsi:schemaLocation="http://www.opengis.net/ows http://schemas.opengis.net/ows/1.0.0/owsExceptionReport.xsd"> | ||
<ows:Exception exceptionCode="InvalidParameterValue" locator="request"> | ||
<ows:ExceptionText>msWFSDispatch(): WFS server error. Invalid WFS request: FooBar</ows:ExceptionText> | ||
</ows:Exception> | ||
</ows:ExceptionReport> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<ows:ExceptionReport xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ows="http://www.opengis.net/ows/1.1" version="2.0.0" xml:lang="en-US" xsi:schemaLocation="http://www.opengis.net/ows/1.1 http://schemas.opengis.net/ows/1.1.0/owsExceptionReport.xsd"> | ||
<ows:Exception exceptionCode="InvalidParameterValue" locator="request"> | ||
<ows:ExceptionText>msWFSDispatch(): WFS server error. Invalid WFS request: FooBar</ows:ExceptionText> | ||
</ows:Exception> | ||
</ows:ExceptionReport> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<ows:ExceptionReport xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ows="http://www.opengis.net/ows/1.1" version="2.0.0" xml:lang="en-US" xsi:schemaLocation="http://www.opengis.net/ows/1.1 http://schemas.opengis.net/ows/1.1.0/owsExceptionReport.xsd"> | ||
<ows:Exception exceptionCode="InvalidParameterValue" locator="request"> | ||
<ows:ExceptionText>msWFSDispatch(): WFS server error. WFS request not enabled. Check wfs/ows_enable_request settings.</ows:ExceptionText> | ||
</ows:Exception> | ||
</ows:ExceptionReport> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
<?xml version='1.0' encoding="UTF-8" ?> | ||
<ServiceExceptionReport version="1.2.0" xmlns="http://www.opengis.net/ogc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/ogc http://schemas.opengis.net/wfs/1.0.0/OGC-exception.xsd"> | ||
<ServiceException code="InvalidParameterValue" locator="request"> | ||
msWFSDispatch(): WFS server error. Invalid WFS request: FooBar | ||
</ServiceException> | ||
</ServiceExceptionReport> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
<?xml version='1.0' encoding="UTF-8" standalone="no" ?> | ||
<!DOCTYPE ServiceExceptionReport SYSTEM "http://schemas.opengis.net/wms/1.1.0/exception_1_1_0.dtd"> | ||
<ServiceExceptionReport version="1.1.0"> | ||
<ServiceException> | ||
msWMSDispatch(): WMS server error. Incomplete or unsupported WMS request | ||
</ServiceException> | ||
</ServiceExceptionReport> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
<?xml version='1.0' encoding="UTF-8" standalone="no" ?> | ||
<!DOCTYPE ServiceExceptionReport SYSTEM "http://schemas.opengis.net/wms/1.1.1/exception_1_1_1.dtd"> | ||
<ServiceExceptionReport version="1.1.1"> | ||
<ServiceException> | ||
msWMSDispatch(): WMS server error. Incomplete or unsupported WMS request | ||
</ServiceException> | ||
</ServiceExceptionReport> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
<?xml version='1.0' encoding="UTF-8" standalone="no" ?> | ||
<ServiceExceptionReport version="1.3.0" xmlns="http://www.opengis.net/ogc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/ogc http://schemas.opengis.net/wms/1.3.0/exceptions_1_3_0.xsd"> | ||
<ServiceException> | ||
msWMSDispatch(): WMS server error. Incomplete or unsupported WMS request | ||
</ServiceException> | ||
</ServiceExceptionReport> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
<?xml version='1.0' encoding="UTF-8" standalone="no" ?> | ||
<ServiceExceptionReport version="1.3.0" xmlns="http://www.opengis.net/ogc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/ogc http://schemas.opengis.net/wms/1.3.0/exceptions_1_3_0.xsd"> | ||
<ServiceException> | ||
msWMSGetCapabilities(): WMS server error. WMS request not enabled. Check wms/ows_enable_request settings. | ||
</ServiceException> | ||
</ServiceExceptionReport> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,181 @@ | ||
// @ts-expect-error ts-migrate(7016) | ||
import wfsCapabilities200 from '../../fixtures/wfs/capabilities-pigma-2-0-0.xml'; | ||
// @ts-expect-error ts-migrate(7016) | ||
import wfsException100 from '../../fixtures/wfs/service-exception-report-1-0-0.xml'; | ||
// @ts-expect-error ts-migrate(7016) | ||
import wfsException110 from '../../fixtures/wfs/exception-report-1-1-0.xml'; | ||
// @ts-expect-error ts-migrate(7016) | ||
import wfsException200 from '../../fixtures/wfs/exception-report-2-0-0.xml'; | ||
// @ts-expect-error ts-migrate(7016) | ||
import wmsException110 from '../../fixtures/wms/service-exception-report-1-1-0.xml'; | ||
// @ts-expect-error ts-migrate(7016) | ||
import wmsException111 from '../../fixtures/wms/service-exception-report-1-1-1.xml'; | ||
// @ts-expect-error ts-migrate(7016) | ||
import wmsException130 from '../../fixtures/wms/service-exception-report-1-3-0.xml'; | ||
import ServiceExceptionError, { | ||
check, | ||
parse, | ||
} from './service-exception-error.js'; | ||
import { | ||
findChildElement, | ||
getRootElement, | ||
parseXmlString, | ||
} from './xml-utils.js'; | ||
|
||
describe('ServiceExceptionError', () => { | ||
describe('it can parse a ServiceException element', () => { | ||
it('can parse a WFS 1.0.0 ServiceException element', () => { | ||
const url = | ||
'http://my.test.service/ogc/wfs?service=WFS&version=1.0.0&request=FooBar'; | ||
const doc = parseXmlString(wfsException100); | ||
const exception = findChildElement( | ||
getRootElement(doc), | ||
'ServiceException' | ||
); | ||
expect(exception).not.toBeNull(); | ||
const error = parse(exception, url); | ||
expect(error).toBeInstanceOf(ServiceExceptionError); | ||
expect(error.code).toBe('InvalidParameterValue'); | ||
expect(error.locator).toBe('request'); | ||
expect(error.message).toBe( | ||
'msWFSDispatch(): WFS server error. Invalid WFS request: FooBar' | ||
); | ||
expect(error.requestUrl).toBe(url); | ||
expect(error.response).toBe(doc); | ||
}); | ||
it('can parse a WFS 1.1.0 ServiceException element', () => { | ||
const url = | ||
'http://my.test.service/ogc/wfs?service=WFS&version=1.1.0&request=FooBar'; | ||
const doc = parseXmlString(wfsException110); | ||
const exception = findChildElement(getRootElement(doc), 'Exception'); | ||
expect(exception).not.toBeNull(); | ||
const error = parse(exception, url); | ||
expect(error).toBeInstanceOf(ServiceExceptionError); | ||
expect(error.code).toBe('InvalidParameterValue'); | ||
expect(error.locator).toBe('request'); | ||
expect(error.message).toBe( | ||
'msWFSDispatch(): WFS server error. Invalid WFS request: FooBar' | ||
); | ||
expect(error.requestUrl).toBe(url); | ||
expect(error.response).toBe(doc); | ||
}); | ||
it('can parse a WFS 2.0.0 Exception element', () => { | ||
const url = | ||
'http://my.test.service/ogc/wfs?service=WFS&version=2.0.0&request=FooBar'; | ||
const doc = parseXmlString(wfsException200); | ||
const exception = findChildElement(getRootElement(doc), 'Exception'); | ||
expect(exception).not.toBeNull(); | ||
const error = parse(exception, url); | ||
expect(error).toBeInstanceOf(ServiceExceptionError); | ||
expect(error.code).toBe('InvalidParameterValue'); | ||
expect(error.locator).toBe('request'); | ||
expect(error.message).toBe( | ||
'msWFSDispatch(): WFS server error. Invalid WFS request: FooBar' | ||
); | ||
expect(error.requestUrl).toBe(url); | ||
expect(error.response).toBe(doc); | ||
}); | ||
it('can parse a WMS 1.1.0 Exception element', () => { | ||
const url = | ||
'http://my.test.service/ogc/wms?service=WMS&version=1.1.0&request=FooBar'; | ||
const doc = parseXmlString(wmsException110); | ||
const exception = findChildElement( | ||
getRootElement(doc), | ||
'ServiceException' | ||
); | ||
expect(exception).not.toBeNull(); | ||
const error = parse(exception, url); | ||
expect(error).toBeInstanceOf(ServiceExceptionError); | ||
expect(error.code).toBe(''); | ||
expect(error.locator).toBe(''); | ||
expect(error.message).toBe( | ||
'msWMSDispatch(): WMS server error. Incomplete or unsupported WMS request' | ||
); | ||
expect(error.requestUrl).toBe(url); | ||
expect(error.response).toBe(doc); | ||
}); | ||
it('can parse a WMS 1.1.1 Exception element', () => { | ||
const url = | ||
'http://my.test.service/ogc/wms?service=WMS&version=1.1.1&request=FooBar'; | ||
const doc = parseXmlString(wmsException111); | ||
const exception = findChildElement( | ||
getRootElement(doc), | ||
'ServiceException' | ||
); | ||
expect(exception).not.toBeNull(); | ||
const error = parse(exception, url); | ||
expect(error).toBeInstanceOf(ServiceExceptionError); | ||
expect(error.code).toBe(''); | ||
expect(error.locator).toBe(''); | ||
expect(error.message).toBe( | ||
'msWMSDispatch(): WMS server error. Incomplete or unsupported WMS request' | ||
); | ||
expect(error.requestUrl).toBe(url); | ||
expect(error.response).toBe(doc); | ||
}); | ||
it('can parse a WMS 1.3.0 Exception element', () => { | ||
const url = | ||
'http://my.test.service/ogc/wms?service=WMS&version=1.3.0&request=FooBar'; | ||
const doc = parseXmlString(wmsException130); | ||
const exception = findChildElement( | ||
getRootElement(doc), | ||
'ServiceException' | ||
); | ||
expect(exception).not.toBeNull(); | ||
const error = parse(exception, url); | ||
expect(error).toBeInstanceOf(ServiceExceptionError); | ||
expect(error.code).toBe(''); | ||
expect(error.locator).toBe(''); | ||
expect(error.message).toBe( | ||
'msWMSDispatch(): WMS server error. Incomplete or unsupported WMS request' | ||
); | ||
expect(error.requestUrl).toBe(url); | ||
expect(error.response).toBe(doc); | ||
}); | ||
}); | ||
|
||
describe('it can check a response document and throw a ServiceExceptionError if necessary', () => { | ||
it('can recognise a WFS 1.0.0 ServiceExceptionReport document', () => { | ||
const url = | ||
'http://my.test.service/ogc/wfs?service=WFS&version=1.0.0&request=FooBar'; | ||
const doc = parseXmlString(wfsException100); | ||
expect(() => check(doc, url)).toThrow(ServiceExceptionError); | ||
}); | ||
it('can recognise a WFS 1.1.0 ExceptionReport document', () => { | ||
const url = | ||
'http://my.test.service/ogc/wfs?service=WFS&version=1.1.0&request=FooBar'; | ||
const doc = parseXmlString(wfsException110); | ||
expect(() => check(doc, url)).toThrow(ServiceExceptionError); | ||
}); | ||
it('can recognise a WFS 2.0.0 ExceptionReport document', () => { | ||
const url = | ||
'http://my.test.service/ogc/wfs?service=WFS&version=2.0.0&request=FooBar'; | ||
const doc = parseXmlString(wfsException200); | ||
expect(() => check(doc, url)).toThrow(ServiceExceptionError); | ||
}); | ||
it('can recognise a WMS 1.1.0 ServiceExceptionReport document', () => { | ||
const url = | ||
'http://my.test.service/ogc/wms?service=WMS&version=1.1.0&request=FooBar'; | ||
const doc = parseXmlString(wmsException110); | ||
expect(() => check(doc, url)).toThrow(ServiceExceptionError); | ||
}); | ||
it('can recognise a WMS 1.1.1 ServiceExceptionReport document', () => { | ||
const url = | ||
'http://my.test.service/ogc/wms?service=WMS&version=1.1.1&request=FooBar'; | ||
const doc = parseXmlString(wmsException111); | ||
expect(() => check(doc, url)).toThrow(ServiceExceptionError); | ||
}); | ||
it('can recognise a WMS 1.3.0 ServiceExceptionReport document', () => { | ||
const url = | ||
'http://my.test.service/ogc/wms?service=WMS&version=1.3.0&request=FooBar'; | ||
const doc = parseXmlString(wmsException130); | ||
expect(() => check(doc, url)).toThrow(ServiceExceptionError); | ||
}); | ||
it('passes the document on if there is no exception reported', () => { | ||
const url = | ||
'http://my.test.service/ogc/wfs?service=WFS&request=GetCapabilities'; | ||
const doc = parseXmlString(wfsCapabilities200); | ||
expect(() => check(doc, url)).not.toThrow(ServiceExceptionError); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
import type { XmlDocument, XmlElement } from '@rgrove/parse-xml'; | ||
import { | ||
findChildElement, | ||
getElementAttribute, | ||
getElementName, | ||
getElementText, | ||
getRootElement, | ||
stripNamespace, | ||
} from '../shared/xml-utils.js'; | ||
|
||
/** | ||
* Representation of an Exception reported by an OWS service | ||
* | ||
* This is usually contained in a ServiceExceptionReport or ExceptionReport | ||
* document and represented as a ServiceException or Exception element | ||
*/ | ||
export default class ServiceExceptionError extends Error { | ||
/** | ||
* Constructor | ||
* @param message Error message | ||
* @param requestUrl URL which resulted in the ServiceException | ||
* @param code Optional ServiceException code | ||
* @param locator Optional ServiceException locator | ||
* @param response Optional response content received | ||
*/ | ||
public constructor( | ||
message: string, | ||
public readonly requestUrl?: string, | ||
public readonly code?: string, | ||
public readonly locator?: string, | ||
public readonly response?: XmlDocument | ||
) { | ||
super(message); | ||
} | ||
} | ||
|
||
/** | ||
* Parse a ServiceException element to a ServiceExceptionError | ||
* @param serviceException ServiceException element | ||
* @param url URL from which the ServiceException was generated | ||
*/ | ||
export function parse( | ||
serviceException: XmlElement, | ||
url?: string | ||
): ServiceExceptionError { | ||
const errorCode = | ||
getElementAttribute(serviceException, 'code') || | ||
getElementAttribute(serviceException, 'exceptionCode'); | ||
const errorLocator = getElementAttribute(serviceException, 'locator'); | ||
const textElement = | ||
findChildElement(serviceException, 'ExceptionText') || serviceException; | ||
const errorMessage = getElementText(textElement).trim(); | ||
return new ServiceExceptionError( | ||
errorMessage, | ||
url, | ||
errorCode, | ||
errorLocator, | ||
serviceException.document | ||
); | ||
} | ||
|
||
/** | ||
* Check the response for a ServiceExceptionReport and if present throw one | ||
* @param response Response to check | ||
* @param url URL from which response was generated | ||
*/ | ||
export function check(response: XmlDocument, url?: string): XmlDocument { | ||
const rootEl = getRootElement(response); | ||
const rootElName = stripNamespace(getElementName(rootEl)); | ||
if (rootElName === 'ServiceExceptionReport') { | ||
// document contains a ServiceExceptionReport, so generate an Error from | ||
// the first ServiceException contained in it | ||
const error = findChildElement(rootEl, 'ServiceException'); | ||
if (error) { | ||
throw parse(error, url); | ||
} | ||
} | ||
if (rootElName === 'ExceptionReport') { | ||
const error = findChildElement(rootEl, 'Exception'); | ||
if (error) { | ||
throw parse(error, url); | ||
} | ||
} | ||
// there was nothing to convert to an Error so just pass the document on | ||
return response; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.