@microsoft.azure/autorest.testserver
Version:
This project contains a set of OpenAPI definitions and a server implementing the corresponding API. Use this to test compliance of AutoRest generators.
585 lines (528 loc) • 18.5 kB
JavaScript
var express = require('express');
var router = express.Router();
var util = require('util');
var utils = require('../util/utils');
var xml2js = require('xml2js');
var util = require('util');
var _ = require('underscore');
var parseXMLString = util.promisify(xml2js.parseString);
var assert = require('assert');
// Expect given request body. Otherwise, 400 with comparison is returned.
var expectXmlBody = function (req, res, body, coverage, testname) {
var rawBody = '';
req.setEncoding('utf8');
req.on('data', function(chunk) { rawBody += chunk });
req.on('end', async function() {
var actualParsedBody, expectedParsedBody;
try {
actualParsedBody = await parseXMLString(rawBody);
expectedParsedBody = await parseXMLString(body);
} catch (err) {
res.status(400).end("XML parse failure: " + err.message);
return;
}
try {
assert.deepStrictEqual(actualParsedBody, expectedParsedBody);
coverage[testname]++;
res.status(201).end();
} catch (err) {
res.status(400).header('Content-Type', 'text/plain').end(`
Expected (parsed form):
${JSON.stringify(err.expected, null, 2)}
Actual (parsed form):
${JSON.stringify(err.actual, null, 2)}
Expected (raw form):
${body}
Actual (raw form):
${rawBody}
`);
}
});
};
var sendXmlBody = function (res, body) {
res.status(200).header('Content-Type', 'application/xml').end(body);
};
// sample XML bodies
var body_list =
`
<EnumerationResults ServiceEndpoint="https://myaccount.blob.core.windows.net/">
<MaxResults>3</MaxResults>
<Containers>
<Container>
<Name>audio</Name>
<Properties>
<Last-Modified>Wed, 26 Oct 2016 20:39:39 GMT</Last-Modified>
<Etag>0x8CACB9BD7C6B1B2</Etag>
<PublicAccess>container</PublicAccess>
</Properties>
</Container>
<Container>
<Name>images</Name>
<Properties>
<Last-Modified>Wed, 26 Oct 2016 20:39:39 GMT</Last-Modified>
<Etag>0x8CACB9BD7C1EEEC</Etag>
</Properties>
</Container>
<Container>
<Name>textfiles</Name>
<Properties>
<Last-Modified>Wed, 26 Oct 2016 20:39:39 GMT</Last-Modified>
<Etag>0x8CACB9BD7BACAC3</Etag>
</Properties>
</Container>
</Containers>
<NextMarker>video</NextMarker>
</EnumerationResults>`;
var body_list_container =
`
<EnumerationResults ContainerName="https://myaccount.blob.core.windows.net/mycontainer">
<Blobs>
<Blob>
<Name>blob1.txt</Name>
<Url>https://myaccount.blob.core.windows.net/mycontainer/blob1.txt</Url>
<Properties>
<Last-Modified>Wed, 09 Sep 2009 09:20:02 GMT</Last-Modified>
<Etag>0x8CBFF45D8A29A19</Etag>
<Content-Length>100</Content-Length>
<Content-Type>text/html</Content-Type>
<Content-Encoding />
<Content-Language>en-US</Content-Language>
<Content-MD5 />
<Cache-Control>no-cache</Cache-Control>
<BlobType>BlockBlob</BlobType>
<LeaseStatus>unlocked</LeaseStatus>
</Properties>
<Metadata>
<Color>blue</Color>
<BlobNumber>01</BlobNumber>
<SomeMetadataName>SomeMetadataValue</SomeMetadataName>
</Metadata>
</Blob>
<Blob>
<Name>blob2.txt</Name>
<Snapshot>2009-09-09T09:20:03.0427659Z</Snapshot>
<Url>https://myaccount.blob.core.windows.net/mycontainer/blob2.txt?snapshot=2009-09-09T09%3a20%3a03.0427659Z</Url>
<Properties>
<Last-Modified>Wed, 09 Sep 2009 09:20:02 GMT</Last-Modified>
<Etag>0x8CBFF45D8B4C212</Etag>
<Content-Length>5000</Content-Length>
<Content-Type>application/octet-stream</Content-Type>
<Content-Encoding>gzip</Content-Encoding>
<Content-Language />
<Content-MD5 />
<Cache-Control />
<BlobType>BlockBlob</BlobType>
</Properties>
<Metadata>
<Color>green</Color>
<BlobNumber>02</BlobNumber>
<SomeMetadataName>SomeMetadataValue</SomeMetadataName>
<x-ms-invalid-name>nasdf$@#$$</x-ms-invalid-name>
</Metadata>
</Blob>
<Blob>
<Name>blob2.txt</Name>
<Snapshot>2009-09-09T09:20:03.1587543Z</Snapshot>
<Url>https://myaccount.blob.core.windows.net/mycontainer/blob2.txt?snapshot=2009-09-09T09%3a20%3a03.1587543Z</Url>
<Properties>
<Last-Modified>Wed, 09 Sep 2009 09:20:02 GMT</Last-Modified>
<Etag>0x8CBFF45D8B4C212</Etag>
<Content-Length>5000</Content-Length>
<Content-Type>application/octet-stream</Content-Type>
<Content-Encoding>gzip</Content-Encoding>
<Content-Language />
<Content-MD5 />
<Cache-Control />
<BlobType>BlockBlob</BlobType>
</Properties>
<Metadata>
<Color>green</Color>
<BlobNumber>02</BlobNumber>
<SomeMetadataName>SomeMetadataValue</SomeMetadataName>
</Metadata>
</Blob>
<Blob>
<Name>blob2.txt</Name>
<Url>https://myaccount.blob.core.windows.net/mycontainer/blob2.txt</Url>
<Properties>
<Last-Modified>Wed, 09 Sep 2009 09:20:02 GMT</Last-Modified>
<Etag>0x8CBFF45D8B4C212</Etag>
<Content-Length>5000</Content-Length>
<Content-Type>application/octet-stream</Content-Type>
<Content-Encoding>gzip</Content-Encoding>
<Content-Language />
<Content-MD5 />
<Cache-Control />
<BlobType>BlockBlob</BlobType>
<LeaseStatus>unlocked</LeaseStatus>
</Properties>
<Metadata>
<Color>green</Color>
<BlobNumber>02</BlobNumber>
<SomeMetadataName>SomeMetadataValue</SomeMetadataName>
</Metadata>
</Blob>
<Blob>
<Name>blob3.txt</Name>
<Url>https://myaccount.blob.core.windows.net/mycontainer/blob3.txt</Url>
<Properties>
<Last-Modified>Wed, 09 Sep 2009 09:20:03 GMT</Last-Modified>
<Etag>0x8CBFF45D911FADF</Etag>
<Content-Length>16384</Content-Length>
<Content-Type>image/jpeg</Content-Type>
<Content-Encoding />
<Content-Language />
<Content-MD5 />
<Cache-Control />
<x-ms-blob-sequence-number>3</x-ms-blob-sequence-number>
<BlobType>PageBlob</BlobType>
<LeaseStatus>locked</LeaseStatus>
</Properties>
<Metadata>
<Color>yellow</Color>
<BlobNumber>03</BlobNumber>
<SomeMetadataName>SomeMetadataValue</SomeMetadataName>
</Metadata>
</Blob>
</Blobs>
<NextMarker />
</EnumerationResults>`
var body_acl_container =
`
<SignedIdentifiers>
<SignedIdentifier>
<Id>MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=</Id>
<AccessPolicy>
<Start>${new Date('2009-09-28T08:49:37.123Z').toISOString()}</Start>
<Expiry>${new Date('2009-09-29T08:49:37.123Z').toISOString()}</Expiry>
<Permission>rwd</Permission>
</AccessPolicy>
</SignedIdentifier>
</SignedIdentifiers>`;
var body_properties_service =
`
<StorageServiceProperties>
<Logging>
<Version>1.0</Version>
<Delete>true</Delete>
<Read>false</Read>
<Write>true</Write>
<RetentionPolicy>
<Enabled>true</Enabled>
<Days>7</Days>
</RetentionPolicy>
</Logging>
<HourMetrics>
<Version>1.0</Version>
<Enabled>true</Enabled>
<IncludeAPIs>false</IncludeAPIs>
<RetentionPolicy>
<Enabled>true</Enabled>
<Days>7</Days>
</RetentionPolicy>
</HourMetrics>
<MinuteMetrics>
<Version>1.0</Version>
<Enabled>true</Enabled>
<IncludeAPIs>true</IncludeAPIs>
<RetentionPolicy>
<Enabled>true</Enabled>
<Days>7</Days>
</RetentionPolicy>
</MinuteMetrics>
</StorageServiceProperties>`;
var xmlService = function (coverage) {
coverage['StorageListContainersXML'] = 0;
coverage['StorageGetServicePropertiesXML'] = 0;
coverage['StoragePutServicePropertiesXML'] = 0;
coverage['StorageGetContainerACLXML'] = 0;
coverage['StorageListBlobsXML'] = 0;
coverage['StoragePutContainerACLXML'] = 0;
coverage['GetSimpleXML'] = 0;
coverage['PutSimpleXML'] = 0;
coverage['GetWrappedXMLList'] = 0;
coverage['PutWrappedXMLList'] = 0;
coverage['GetEmptyXMLList'] = 0;
coverage['PutEmptyXMLList'] = 0;
coverage['GetEmptyWrappedXMLList'] = 0;
coverage['PutEmptyWrappedXMLList'] = 0;
coverage['GetXMLListAtRoot'] = 0;
coverage['PutXMLListAtRoot'] = 0;
coverage['GetXMLListAtRootSingle'] = 0;
coverage['PutXMLListAtRootSingle'] = 0;
coverage['GetEmptyXMLListAtRoot'] = 0;
coverage['PutEmptyXMLListAtRoot'] = 0;
coverage['GetXMLEmptyNode'] = 0;
coverage['PutXMLEmptyNode'] = 0;
coverage['GetRootWithRefAndNoMetaXML'] = 0;
coverage['PutRootWithRefAndNoMetaXML'] = 0;
coverage['GetRootWithRefAndMetaXML'] = 0;
coverage['PutRootWithRefAndMetaXML'] = 0;
coverage['jsonInputInXMLSwagger'] = 0;
coverage['jsonOutputInXMLSwagger'] = 0;
router.get('/', function (req, res, next) {
var comp = req.query.comp;
var restype = req.query.restype;
switch(comp) {
case "list":
switch(restype) {
// https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/list-containers2
// https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/enumerating-blob-resources
// Swagger: Service_ListContainers
case undefined:
sendXmlBody(res, body_list);
coverage['StorageListContainersXML']++;
break;
default: res.sendStatus(404); break;
}
break;
case "properties":
switch(restype) {
// https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/get-blob-service-properties
// Swagger: Service_GetServiceProperties
case "service":
sendXmlBody(res, body_properties_service);
coverage['StorageGetServicePropertiesXML']++;
break;
default: res.sendStatus(404); break;
}
break;
default: res.sendStatus(404); break;
}
});
router.put('/', function (req, res, next) {
var comp = req.query.comp;
var restype = req.query.restype;
switch(comp) {
case "properties":
switch(restype) {
// https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/set-blob-service-properties
case "service":
expectXmlBody(req, res, body_properties_service, coverage, 'StoragePutServicePropertiesXML');
break;
default: res.sendStatus(404); break;
}
break;
default: res.sendStatus(404); break;
}
});
router.get('/mycontainer', function (req, res, next) {
var comp = req.query.comp;
var restype = req.query.restype;
switch(comp) {
case "acl":
switch(restype) {
// https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/get-container-acl
case "container":
sendXmlBody(res, body_acl_container);
coverage['StorageGetContainerACLXML']++;
break;
default: res.sendStatus(404); break;
}
break;
case "list":
switch(restype) {
// https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/list-blobs
// https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/enumerating-blob-resources
// Swagger: Containers_ListBlobs
case "container":
sendXmlBody(res, body_list_container);
coverage['StorageListBlobsXML']++;
break;
default: res.sendStatus(404); break;
}
break;
default: res.sendStatus(404); break;
}
});
router.put('/mycontainer', function (req, res, next) {
var comp = req.query.comp;
var restype = req.query.restype;
switch(comp) {
case "acl":
switch(restype) {
// https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/set-container-acl
case "container":
expectXmlBody(req, res, body_acl_container, coverage, 'StoragePutContainerACLXML');
break;
default: res.sendStatus(404); break;
}
break;
default: res.sendStatus(404); break;
}
});
const simpleBody =
`
<slideshow
title="Sample Slide Show"
date="Date of publication"
author="Yours Truly">
<slide type="all">
<title>Wake up to WonderWidgets!</title>
</slide>
<slide type="all">
<title>Overview</title>
<item>Why WonderWidgets are great</item>
<item></item>
<item>Who buys WonderWidgets</item>
</slide>
</slideshow>`;
router.get('/simple', function (req, res) {
sendXmlBody(res, simpleBody);
coverage['GetSimpleXML']++;
});
router.put('/simple', function(req, res) {
expectXmlBody(req, res, simpleBody, coverage, 'PutSimpleXML');
});
const wrappedListsBody =
`
<AppleBarrel>
<GoodApples>
<Apple>Fuji</Apple>
<Apple>Gala</Apple>
</GoodApples>
<BadApples>
<Apple>Red Delicious</Apple>
</BadApples>
</AppleBarrel>`
router.get('/wrapped-lists', function (req, res) {
sendXmlBody(res, wrappedListsBody);
coverage['GetWrappedXMLList']++;
});
router.put('/wrapped-lists', function(req, res) {
expectXmlBody(req, res, wrappedListsBody, coverage, 'PutWrappedXMLList');
});
const emptyListBody =
`
<slideshow/>`;
router.get('/empty-list', function (req, res) {
sendXmlBody(res, emptyListBody);
coverage['GetEmptyXMLList']++;
});
router.put('/empty-list', function (req, res) {
expectXmlBody(req, res, emptyListBody, coverage, 'PutEmptyXMLList');
});
const emptyWrappedListsBody =
`
<AppleBarrel>
<GoodApples></GoodApples>
<BadApples/>
</AppleBarrel>`;
router.get('/empty-wrapped-lists', function (req, res) {
sendXmlBody(res, emptyWrappedListsBody);
coverage['GetEmptyWrappedXMLList']++;
});
router.put('/empty-wrapped-lists', function (req, res) {
expectXmlBody(req, res, emptyWrappedListsBody, coverage, 'PutEmptyWrappedXMLList');
});
const rootListBody =
`
<bananas>
<banana>
<name>Cavendish</name>
<flavor>Sweet</flavor>
<expiration>${new Date('2018-02-28T00:40:00.123Z').toISOString()}</expiration>
</banana>
<banana>
<name>Plantain</name>
<flavor>Savory</flavor>
<expiration>${new Date('2018-02-28T00:40:00.123Z').toISOString()}</expiration>
</banana>
</bananas>`
router.get('/root-list', function (req, res) {
sendXmlBody(res, rootListBody);
coverage['GetXMLListAtRoot']++;
});
router.put('/root-list', function(req, res) {
expectXmlBody(req, res, rootListBody, coverage, 'PutXMLListAtRoot');
});
const rootListSingleItemBody =
`
<bananas>
<banana>
<name>Cavendish</name>
<flavor>Sweet</flavor>
<expiration>${new Date('2018-02-28T00:40:00.123Z').toISOString()}</expiration>
</banana>
</bananas>`
router.get('/root-list-single-item', function (req, res) {
sendXmlBody(res, rootListSingleItemBody);
coverage['GetXMLListAtRootSingle']++;
});
router.put('/root-list-single-item', function(req, res) {
expectXmlBody(req, res, rootListSingleItemBody, coverage, 'PutXMLListAtRootSingle');
});
const emptyRootListBody =
`
<bananas/>`;
router.get('/empty-root-list', function (req, res) {
sendXmlBody(res, emptyRootListBody);
coverage['GetEmptyXMLListAtRoot']++;
});
router.put('/empty-root-list', function(req, res) {
expectXmlBody(req, res, emptyRootListBody, coverage, 'PutEmptyXMLListAtRoot');
});
const emptyChildElementBody =
`
<banana>
<name>Unknown Banana</name>
<flavor></flavor>
<expiration>${new Date('2012-02-24T00:53:52.789Z').toISOString()}</expiration>
</banana>`
router.get('/empty-child-element', function (req, res) {
sendXmlBody(res, emptyChildElementBody);
coverage['GetXMLEmptyNode']++;
});
router.put('/empty-child-element', function(req, res) {
expectXmlBody(req, res, emptyChildElementBody, coverage, 'PutXMLEmptyNode');
});
const complexTypeRefComplexTypeWithNoXMLmeta =
`
<RootWithRefAndNoMeta>
<RefToModel>
<ID>myid</ID>
</RefToModel>
<Something>else</Something>
</RootWithRefAndNoMeta>`
router.get('/complex-type-ref-no-meta', function (req, res) {
coverage['GetRootWithRefAndNoMetaXML']++;
sendXmlBody(res, complexTypeRefComplexTypeWithNoXMLmeta);
});
router.put('/complex-type-ref-no-meta', function(req, res) {
expectXmlBody(req, res, complexTypeRefComplexTypeWithNoXMLmeta, coverage, 'PutRootWithRefAndNoMetaXML');
});
const complexTypeRefComplexTypeWithXMLmeta =
`
<RootWithRefAndMeta>
<XMLComplexTypeWithMeta>
<ID>myid</ID>
</XMLComplexTypeWithMeta>
<Something>else</Something>
</RootWithRefAndMeta>`
router.get('/complex-type-ref-with-meta', function (req, res) {
coverage['GetRootWithRefAndMetaXML']++;
sendXmlBody(res, complexTypeRefComplexTypeWithXMLmeta);
});
router.put('/complex-type-ref-with-meta', function(req, res) {
expectXmlBody(req, res, complexTypeRefComplexTypeWithXMLmeta, coverage, 'PutRootWithRefAndMetaXML');
});
router.get('/headers', function (req, res) {
res.status(200);
res.setHeader("Custom-HEADER", "custom-value");
res.end();
});
router.put('/jsoninput', function (req, res, next) {
if (_.isEqual(req.body, { "id": 42 })) {
coverage['jsonInputInXMLSwagger']++;
res.status(200).end();
} else {
utils.send400(res, next, "Did not like valid req " + util.inspect(req.body));
}
});
router.get('/jsonoutput', function (req, res, next) {
coverage['jsonOutputInXMLSwagger']++;
res.status(200).json({ "id": 42 });
});
};
xmlService.prototype.router = router;
module.exports = xmlService;