Splitting library to remove dependency of Windows.Storage (#227)
This commit is contained in:
Родитель
9d2162c1bd
Коммит
d43914febe
63
README.md
63
README.md
|
@ -11,15 +11,16 @@
|
|||
| Component | Build Status | NuGet Package |
|
||||
|:-|---|---|
|
||||
| nanoFramework.WebServer | [![Build Status](https://dev.azure.com/nanoframework/nanoFramework.WebServer/_apis/build/status/nanoFramework.WebServer?repoName=nanoframework%2FnanoFramework.WebServer&branchName=main)](https://dev.azure.com/nanoframework/nanoFramework.WebServer/_build/latest?definitionId=65&repoName=nanoframework%2FnanoFramework.WebServer&branchName=main) | [![NuGet](https://img.shields.io/nuget/v/nanoFramework.WebServer.svg?label=NuGet&style=flat&logo=nuget)](https://www.nuget.org/packages/nanoFramework.WebServer/) |
|
||||
| nanoFramework.WebServer.FileSystem | [![Build Status](https://dev.azure.com/nanoframework/nanoFramework.WebServer/_apis/build/status/nanoFramework.WebServer?repoName=nanoframework%2FnanoFramework.WebServer&branchName=main)](https://dev.azure.com/nanoframework/nanoFramework.WebServer/_build/latest?definitionId=65&repoName=nanoframework%2FnanoFramework.WebServer&branchName=main) | [![NuGet](https://img.shields.io/nuget/v/nanoFramework.WebServer.FileSystem.svg?label=NuGet&style=flat&logo=nuget)](https://www.nuget.org/packages/nanoFramework.WebServer.FileSystem/) |
|
||||
|
||||
## .NET nanoFramework WebServer
|
||||
|
||||
This library was coded by [Laurent Ellerbach](@Ellerbach) who generously offered it to the .NET **nanoFramework** project.
|
||||
This library was coded by [Laurent Ellerbach](https://github.com/Ellerbach) who generously offered it to the .NET **nanoFramework** project.
|
||||
|
||||
This is a simple nanoFramework WebServer. Features:
|
||||
|
||||
- Handle multi-thread requests
|
||||
- Serve static files on any storage
|
||||
- Serve static files from any storage using [`nanoFramework.WebServer.FileSystem` NuGet](https://www.nuget.org/packages/nanoFramework.WebServer.FileSystem). Requires a target device with support for storage (having `System.IO.FileSystem` capability).
|
||||
- Handle parameter in URL
|
||||
- Possible to have multiple WebServer running at the same time
|
||||
- supports GET/PUT and any other word
|
||||
|
@ -31,6 +32,7 @@ This is a simple nanoFramework WebServer. Features:
|
|||
- [URL decode/encode](https://github.com/nanoframework/lib-nanoFramework.System.Net.Http/blob/develop/nanoFramework.System.Net.Http/Http/System.Net.HttpUtility.cs)
|
||||
|
||||
Limitations:
|
||||
|
||||
- Does not support any zip in the request or response stream
|
||||
|
||||
## Usage
|
||||
|
@ -93,9 +95,10 @@ The `RouteAnyTest`is called whenever the url is `test/any` whatever the method i
|
|||
|
||||
There is a more advance example with simple REST API to get a list of Person and add a Person. Check it in the [sample](./WebServer.Sample/ControllerPerson.cs).
|
||||
|
||||
**Important**
|
||||
* By default the routes are not case sensitive and the attribute **must** be lowercase
|
||||
* If you want to use case sensitive routes like in the previous example, use the attribute `CaseSensitive`. As in the previous example, you **must** write the route as you want it to be responded to.
|
||||
> [!Important]
|
||||
>
|
||||
> By default the routes are not case sensitive and the attribute **must** be lowercase.
|
||||
> If you want to use case sensitive routes like in the previous example, use the attribute `CaseSensitive`. As in the previous example, you **must** write the route as you want it to be responded to.
|
||||
|
||||
## A simple GPIO controller REST API
|
||||
|
||||
|
@ -113,13 +116,13 @@ You will find in simple [GPIO controller sample](https://github.com/nanoframewor
|
|||
Controllers support authentication. 3 types of authentications are currently implemented on controllers only:
|
||||
|
||||
- Basic: the classic user and password following the HTTP standard. Usage:
|
||||
- `[Authentication("Basic")]` will use the default credential of the webserver
|
||||
- `[Authentication("Basic:myuser mypassword")]` will use myuser as a user and my password as a password. Note: the user cannot contains spaces.
|
||||
- `[Authentication("Basic")]` will use the default credential of the webserver
|
||||
- `[Authentication("Basic:myuser mypassword")]` will use myuser as a user and my password as a password. Note: the user cannot contains spaces.
|
||||
- APiKey in header: add ApiKey in headers with the API key. Usage:
|
||||
- `[Authentication("ApiKey")]` will use the default credential of the webserver
|
||||
- `[Authentication("ApiKeyc:akey")]` will use akey as ApiKey.
|
||||
- `[Authentication("ApiKey")]` will use the default credential of the webserver
|
||||
- `[Authentication("ApiKeyc:akey")]` will use akey as ApiKey.
|
||||
- None: no authentication required. Usage:
|
||||
- `[Authentication("None")]` will use the default credential of the webserver
|
||||
- `[Authentication("None")]` will use the default credential of the webserver
|
||||
|
||||
The Authentication attribute applies to both public Classes an public Methods.
|
||||
|
||||
|
@ -184,9 +187,9 @@ using (WebServer server = new WebServer(80, HttpProtocol.Http, new Type[] { type
|
|||
With the previous example the following happens:
|
||||
|
||||
- All the controller by default, even when nothing is specified will use the controller credentials. In our case, the Basic authentication with the default user (topuser) and password (topPassword) will be used.
|
||||
- When calling http://yoururl/authbasic from a browser, you will be prompted for the user and password, use the default one topuser and topPassword to get access
|
||||
- When calling http://yoururl/authnone, you won't be prompted because the authentication has been overridden for no authentication
|
||||
- When calling http://yoururl/authbasicspecial, the user and password are different from the defautl ones, user2 and password is the right couple here
|
||||
- When calling http://yoururl/authbasic from a browser, you will be prompted for the user and password, use the default one topuser and topPassword to get access
|
||||
- When calling http://yoururl/authnone, you won't be prompted because the authentication has been overridden for no authentication
|
||||
- When calling http://yoururl/authbasicspecial, the user and password are different from the defautl ones, user2 and password is the right couple here
|
||||
- If you would have define in the controller a specific user and password like `[Authentication("Basic:myuser mypassword")]`, then the default one for all the controller would have been myuser and mypassword
|
||||
- When calling http://yoururl/authapi, you must pass the header `ApiKey` (case sensitive) with the value `superKey1234` to get authorized, this is overridden the default Basic authentication
|
||||
- When calling http://yoururl/authdefaultapi, the default key `ATopSecretAPIKey1234` will be used so you have to pass it in the headers of the request
|
||||
|
@ -246,12 +249,31 @@ if (url.ToLower().IndexOf("/param.htm") == 0)
|
|||
And server static files:
|
||||
|
||||
```csharp
|
||||
var files = storage.GetFiles();
|
||||
foreach (var file in files)
|
||||
// E = USB storage
|
||||
// D = SD Card
|
||||
// I = Internal storage
|
||||
// Adjust this based on your configuration
|
||||
const string DirectoryPath = "I:\\";
|
||||
string[] _listFiles;
|
||||
|
||||
// Gets the list of all files in a specific directory
|
||||
// See the MountExample for more details if you need to mount an SD card and adjust here
|
||||
// https://github.com/nanoframework/Samples/blob/main/samples/System.IO.FileSystem/MountExample/Program.cs
|
||||
_listFiles = Directory.GetFiles(DirectoryPath);
|
||||
// Remove the root directory
|
||||
for (int i = 0; i < _listFiles.Length; i++)
|
||||
{
|
||||
if (file.Name == url)
|
||||
_listFiles[i] = _listFiles[i].Substring(DirectoryPath.Length);
|
||||
}
|
||||
|
||||
var fileName = url.Substring(1);
|
||||
// Note that the file name is case sensitive
|
||||
// Very simple example serving a static file on an SD card
|
||||
foreach (var file in _listFiles)
|
||||
{
|
||||
if (file == fileName)
|
||||
{
|
||||
WebServer.SendFileOverHTTP(e.Context.Response, file);
|
||||
WebServer.SendFileOverHTTP(e.Context.Response, DirectoryPath + file);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -259,6 +281,10 @@ foreach (var file in files)
|
|||
WebServer.OutputHttpCode(e.Context.Response, HttpStatusCode.NotFound);
|
||||
```
|
||||
|
||||
> [!Important]
|
||||
>
|
||||
> Serving files requires the `nanoFramework.WebServer.FileSystem` nuget **AND** that the device supports storage so `System.IO.FileSystem`.
|
||||
|
||||
And also **REST API** is supported, here is a comprehensive example:
|
||||
|
||||
```csharp
|
||||
|
@ -363,7 +389,8 @@ using (WebServer server = new WebServer(443, HttpProtocol.Https)
|
|||
}
|
||||
```
|
||||
|
||||
> IMPORTANT: because the certificate above is not issued from a Certificate Authority it won't be recognized as a valid certificate. If you want to access the nanoFramework device with your browser, for example, you'll have to add the (CRT file)[WebServer.Sample\webserver-cert.crt] as a trusted one. On Windows, you just have to double click on the CRT file and then click "Install Certificate...".
|
||||
> [!IMPORTANT]
|
||||
> Because the certificate above is not issued from a Certificate Authority it won't be recognized as a valid certificate. If you want to access the nanoFramework device with your browser, for example, you'll have to add the [CRT file](WebServer.Sample\webserver-cert.crt) as a trusted one. On Windows, you just have to double click on the CRT file and then click "Install Certificate...".
|
||||
|
||||
You can of course use the routes as defined earlier. Both will work, event or route with the notion of controller.
|
||||
|
||||
|
|
|
@ -46,10 +46,46 @@ steps:
|
|||
|
||||
# step from template @ nf-tools repo
|
||||
# all build, update and publish steps
|
||||
- template: azure-pipelines-templates/class-lib-build.yml@templates
|
||||
- template: azure-pipelines-templates/class-lib-build-only.yml@templates
|
||||
parameters:
|
||||
sonarCloudProject: 'nanoframework_lib-nanoframework.WebServer'
|
||||
|
||||
# build the 2 libs step
|
||||
- template: azure-pipelines-templates/class-lib-package.yml@templates
|
||||
parameters:
|
||||
nugetPackageName: 'nanoFramework.WebServer'
|
||||
|
||||
- template: azure-pipelines-templates/class-lib-package.yml@templates
|
||||
parameters:
|
||||
nugetPackageName: 'nanoFramework.WebServer.FileSystem'
|
||||
|
||||
# publish the 2 libs
|
||||
- template: azure-pipelines-templates/class-lib-publish.yml@templates
|
||||
|
||||
# create GitHub release build from main branch
|
||||
- task: GithubRelease@1
|
||||
condition: >-
|
||||
and(
|
||||
succeeded(),
|
||||
eq(variables['System.PullRequest.PullRequestId'], ''),
|
||||
startsWith(variables['Build.SourceBranch'], 'refs/heads/main'),
|
||||
not(contains(variables['Build.SourceBranch'], 'preview')),
|
||||
eq(variables['StartReleaseCandidate'], false)
|
||||
)
|
||||
displayName: Create/Update GitHub release
|
||||
inputs:
|
||||
action: edit
|
||||
gitHubConnection: 'github.com_nano-$(System.TeamProject)'
|
||||
tagSource: userSpecifiedTag
|
||||
tag: v$(MY_NUGET_VERSION)
|
||||
title: '$(nugetPackageName) Library v$(MY_NUGET_VERSION)'
|
||||
releaseNotesSource: inline
|
||||
releaseNotesInline: 'Check the [changelog]($(Build.Repository.Uri)/blob/$(Build.SourceBranchName)/CHANGELOG.md).<br><br><h4>Install from NuGet</h4><br>The following NuGet packages are available for download from this release:<br>:package: [nanoFramework.WebServer](https://www.nuget.org/packages/$(nugetPackageName)/$(MY_NUGET_VERSION)) v$(MY_NUGET_VERSION).<br>:package: [nanoFramework.WebServer.FileSystem (requires support of storage through System.IO.FileSystem)](https://www.nuget.org/packages/nanoFramework.WebServer.FileSystem/$(MY_NUGET_VERSION)) v$(MY_NUGET_VERSION)'
|
||||
assets: '$(Build.ArtifactStagingDirectory)/*.nupkg'
|
||||
assetUploadMode: replace
|
||||
isPreRelease: false
|
||||
addChangeLog: false
|
||||
|
||||
# step from template @ nf-tools repo
|
||||
# report error
|
||||
- template: azure-pipelines-templates/discord-webhook-task.yml@templates
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>nanoFramework.WebServer.FileServer</id>
|
||||
<title>nanoFramework.WebServer.FileServer</title>
|
||||
<version>$version$</version>
|
||||
<authors>Laurent Ellerbach,nanoframework</authors>
|
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<license type="file">LICENSE.md</license>
|
||||
<releaseNotes>
|
||||
</releaseNotes>
|
||||
<readme>docs\README.md</readme>
|
||||
<developmentDependency>false</developmentDependency>
|
||||
<projectUrl>https://github.com/nanoframework/nanoFramework.WebServer</projectUrl>
|
||||
<icon>images\nf-logo.png</icon>
|
||||
<repository type="git" url="https://github.com/nanoframework/nanoFramework.WebServer" commit="$commit$" />
|
||||
<copyright>Copyright (c) .NET Foundation and Contributors</copyright>
|
||||
<description>This is a simple multithread WebServer supporting simple controller and event based calls.
|
||||
Perfect for .NET nanoFramework REST API based project. Support all type of Http Methods.
|
||||
Perfect for simple embedded web pages, with Support of file on a storage (USB, SD Card, in Memory).
|
||||
Supports both HTTPS and HTTP.
|
||||
Use this version if you want to serve local files and have support for System.IO.FileSystem on your device.
|
||||
Otherwise use 'nanoFramework.WebServer' nuget.</description>
|
||||
<tags>http https webserver net netmf nf nanoframework</tags>
|
||||
<dependencies>
|
||||
<dependency id="nanoFramework.CoreLibrary" version="1.14.2" />
|
||||
<dependency id="nanoFramework.System.Net.Http.Server" version="1.5.104" />
|
||||
<dependency id="nanoFramework.System.IO.FileSystem" version="1.1.23" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
<files>
|
||||
<file src="nanoFramework.WebServer\bin\Release\nanoFramework.WebServer.*" target="lib" />
|
||||
<file src="assets\readme.txt" target="" />
|
||||
<file src="README.md" target="docs\" />
|
||||
<file src="assets\nf-logo.png" target="images" />
|
||||
<file src="LICENSE.md" target="" />
|
||||
</files>
|
||||
</package>
|
|
@ -0,0 +1,18 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("nanoFramework.WebServer")]
|
||||
[assembly: AssemblyCompany("nanoFramework Contributors")]
|
||||
[assembly: AssemblyProduct("nanoFramework.WebServer.FileSystem")]
|
||||
[assembly: AssemblyCopyright("Copyright (c) .NET Foundation and Contributors")]
|
||||
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
|
@ -0,0 +1,131 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Label="Globals">
|
||||
<NanoFrameworkProjectSystemPath>$(MSBuildExtensionsPath)\nanoFramework\v1.0\</NanoFrameworkProjectSystemPath>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.Default.props" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.Default.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectTypeGuids>{11A8DD76-328B-46DF-9F39-F559912D0360};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<ProjectGuid>9d8a2d18-8036-4880-b46b-d5218247257d</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<RootNamespace>nanoFramework.WebServer</RootNamespace>
|
||||
<AssemblyName>nanoFramework.WebServer</AssemblyName>
|
||||
<TargetFrameworkVersion>v1.0</TargetFrameworkVersion>
|
||||
<DocumentationFile>bin\$(Configuration)\nanoFramework.WebServer.xml</DocumentationFile>
|
||||
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
|
||||
<RestoreLockedMode Condition="'$(TF_BUILD)' == 'True' or '$(ContinuousIntegrationBuild)' == 'True'">true</RestoreLockedMode>
|
||||
<DefineConstants>FILESYSTEM;</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<AssemblyOriginatorKeyFile>..\key.snk</AssemblyOriginatorKeyFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<DelaySign>false</DelaySign>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.props" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.props')" />
|
||||
<ItemGroup>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="..\nanoFramework.WebServer\Authentication.cs" >
|
||||
<Link>Authentication.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\nanoFramework.WebServer\AuthenticationAttirbute.cs" >
|
||||
<Link>AuthenticationAttirbute.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\nanoFramework.WebServer\AuthenticationType.cs" >
|
||||
<Link>AuthenticationType.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\nanoFramework.WebServer\CallbackRoutes.cs" >
|
||||
<Link>CallbackRoutes.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\nanoFramework.WebServer\CaseSensitiveAttribute.cs" >
|
||||
<Link>CaseSensitiveAttribute.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\nanoFramework.WebServer\HttpProtocol.cs" >
|
||||
<Link>HttpProtocol.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\nanoFramework.WebServer\WebServerEventArgs.cs" >
|
||||
<Link>WebServerEventArgs.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\nanoFramework.WebServer\Header.cs" >
|
||||
<Link>Header.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\nanoFramework.WebServer\MethodAttribute.cs" >
|
||||
<Link>MethodAttribute.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\nanoFramework.WebServer\RouteAttribute.cs" >
|
||||
<Link>RouteAttribute.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\nanoFramework.WebServer\UrlParameter.cs" >
|
||||
<Link>UrlParameter.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\nanoFramework.WebServer\WebServer.cs" >
|
||||
<Link>WebServer.cs</Link>
|
||||
</Compile>
|
||||
<None Include="..\key.snk" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="mscorlib, Version=1.14.3.0, Culture=neutral, PublicKeyToken=c07d481e9758c731">
|
||||
<HintPath>..\packages\nanoFramework.CoreLibrary.1.14.2\lib\mscorlib.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="nanoFramework.Runtime.Events, Version=1.11.6.0, Culture=neutral, PublicKeyToken=c07d481e9758c731">
|
||||
<HintPath>..\packages\nanoFramework.Runtime.Events.1.11.6\lib\nanoFramework.Runtime.Events.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="nanoFramework.System.Collections, Version=1.5.18.0, Culture=neutral, PublicKeyToken=c07d481e9758c731">
|
||||
<HintPath>..\packages\nanoFramework.System.Collections.1.5.18\lib\nanoFramework.System.Collections.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="nanoFramework.System.Text, Version=1.2.37.0, Culture=neutral, PublicKeyToken=c07d481e9758c731">
|
||||
<HintPath>..\packages\nanoFramework.System.Text.1.2.37\lib\nanoFramework.System.Text.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.IO.Streams, Version=1.1.38.0, Culture=neutral, PublicKeyToken=c07d481e9758c731">
|
||||
<HintPath>..\packages\nanoFramework.System.IO.Streams.1.1.38\lib\System.IO.Streams.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Net, Version=1.10.62.0, Culture=neutral, PublicKeyToken=c07d481e9758c731">
|
||||
<HintPath>..\packages\nanoFramework.System.Net.1.10.62\lib\System.Net.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Net.Http, Version=1.5.104.0, Culture=neutral, PublicKeyToken=c07d481e9758c731">
|
||||
<HintPath>..\packages\nanoFramework.System.Net.Http.Server.1.5.104\lib\System.Net.Http.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Threading, Version=1.1.19.33722, Culture=neutral, PublicKeyToken=c07d481e9758c731">
|
||||
<HintPath>..\packages\nanoFramework.System.Threading.1.1.19\lib\System.Threading.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.IO">
|
||||
<HintPath>..\packages\nanoFramework.System.IO.FileSystem.1.1.23\lib\System.IO.FileSystem.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="packages.lock.json" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.CSharp.targets" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.CSharp.targets')" />
|
||||
<ProjectExtensions>
|
||||
<ProjectCapabilities>
|
||||
<ProjectConfigurationsDeclaredAsItems />
|
||||
</ProjectCapabilities>
|
||||
</ProjectExtensions>
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105.The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\packages\Nerdbank.GitVersioning.3.6.133\build\Nerdbank.GitVersioning.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Nerdbank.GitVersioning.3.6.133\build\Nerdbank.GitVersioning.props'))" />
|
||||
<Error Condition="!Exists('..\packages\Nerdbank.GitVersioning.3.6.133\build\Nerdbank.GitVersioning.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Nerdbank.GitVersioning.3.6.133\build\Nerdbank.GitVersioning.targets'))" />
|
||||
</Target>
|
||||
<Import Project="..\packages\Nerdbank.GitVersioning.3.6.133\build\Nerdbank.GitVersioning.targets" Condition="Exists('..\packages\Nerdbank.GitVersioning.3.6.133\build\Nerdbank.GitVersioning.targets')" />
|
||||
</Project>
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="nanoFramework.CoreLibrary" version="1.14.2" targetFramework="netnano1.0" />
|
||||
<package id="nanoFramework.Runtime.Events" version="1.11.6" targetFramework="netnano1.0" />
|
||||
<package id="nanoFramework.System.Collections" version="1.5.18" targetFramework="netnano1.0" />
|
||||
<package id="nanoFramework.System.IO.FileSystem" version="1.1.23" targetFramework="netnano1.0" />
|
||||
<package id="nanoFramework.System.IO.Streams" version="1.1.38" targetFramework="netnano1.0" />
|
||||
<package id="nanoFramework.System.Net" version="1.10.62" targetFramework="netnano1.0" />
|
||||
<package id="nanoFramework.System.Net.Http.Server" version="1.5.104" targetFramework="netnano1.0" />
|
||||
<package id="nanoFramework.System.Text" version="1.2.37" targetFramework="netnano1.0" />
|
||||
<package id="nanoFramework.System.Threading" version="1.1.19" targetFramework="netnano1.0" />
|
||||
<package id="Nerdbank.GitVersioning" version="3.6.133" developmentDependency="true" targetFramework="netnano1.0" />
|
||||
</packages>
|
|
@ -0,0 +1,67 @@
|
|||
{
|
||||
"version": 1,
|
||||
"dependencies": {
|
||||
".NETnanoFramework,Version=v1.0": {
|
||||
"nanoFramework.CoreLibrary": {
|
||||
"type": "Direct",
|
||||
"requested": "[1.14.2, 1.14.2]",
|
||||
"resolved": "1.14.2",
|
||||
"contentHash": "j1mrz4mitl5LItvmHMsw1aHzCAfvTTgIkRxA0mhs5mSpctJ/BBcuNwua5j3MspfRNKreCQPy/qZy/D9ADLL/PA=="
|
||||
},
|
||||
"nanoFramework.Runtime.Events": {
|
||||
"type": "Direct",
|
||||
"requested": "[1.11.6, 1.11.6]",
|
||||
"resolved": "1.11.6",
|
||||
"contentHash": "xkltRh/2xKaZ9zmPHbVr32s1k+e17AInUBhzxKKkUDicJKF39yzTShSklb1OL6DBER5z71SpkGLyl9IdMK9l6w=="
|
||||
},
|
||||
"nanoFramework.System.Collections": {
|
||||
"type": "Direct",
|
||||
"requested": "[1.5.18, 1.5.18]",
|
||||
"resolved": "1.5.18",
|
||||
"contentHash": "F8FzaUC5D2xd6eQja33EYcknOFqWT+YEcnEn849ILJTGSedVFylUREEuoGULbCrnuuLx417hDzWny+B78Qi67g=="
|
||||
},
|
||||
"nanoFramework.System.IO.FileSystem": {
|
||||
"type": "Direct",
|
||||
"requested": "[1.1.23, 1.1.23]",
|
||||
"resolved": "1.1.23",
|
||||
"contentHash": "W8HMgL81baCutM9isIqeOHU5SM6J3z1g1XF16quVtK8DARQzKdwLV+fJweXyOUTnpyXV/oEkr9SrkCdGdBPliQ=="
|
||||
},
|
||||
"nanoFramework.System.IO.Streams": {
|
||||
"type": "Direct",
|
||||
"requested": "[1.1.38, 1.1.38]",
|
||||
"resolved": "1.1.38",
|
||||
"contentHash": "qEtu/lMDtr5kPKc939vO3uX8h+W0/+Qx2N3Zx005JxqGiL71e4ScecEyGPIp8v1MzRd9pkoxInUb6jOAh+eyXA=="
|
||||
},
|
||||
"nanoFramework.System.Net": {
|
||||
"type": "Direct",
|
||||
"requested": "[1.10.62, 1.10.62]",
|
||||
"resolved": "1.10.62",
|
||||
"contentHash": "MR4PIS7J+LyPU6jSbVu0+tdeBb3lXo7xPun+C0Q3zMpc9YPPCsI7euko4O3Q4T7VSbtjeA3dDfI0fsefcgVRUA=="
|
||||
},
|
||||
"nanoFramework.System.Net.Http.Server": {
|
||||
"type": "Direct",
|
||||
"requested": "[1.5.104, 1.5.104]",
|
||||
"resolved": "1.5.104",
|
||||
"contentHash": "zU0NkMd3269In8AnVKPsg9Ai3Px49rjw4aldQahxSRgqTDoej0YrM/ielgIsGQT3vas0gJiEpcF6fV0i5gf4WA=="
|
||||
},
|
||||
"nanoFramework.System.Text": {
|
||||
"type": "Direct",
|
||||
"requested": "[1.2.37, 1.2.37]",
|
||||
"resolved": "1.2.37",
|
||||
"contentHash": "ORgRq0HSynSBhlXRTHdhzZiOdq/nRhdnX+DeIGw56y9OSc8dvqUz6elm97Jz+4WQ6ikpvs5PFGINAa35kBebwQ=="
|
||||
},
|
||||
"nanoFramework.System.Threading": {
|
||||
"type": "Direct",
|
||||
"requested": "[1.1.19, 1.1.19]",
|
||||
"resolved": "1.1.19",
|
||||
"contentHash": "HjnY0DNoFnU+t1GiH8Wgf7pJCD9yMOcLVtAZXVAhstMKisVN/MDj9TvfXxZScRIz7ZDoZYUnb+Ixfl6rqyppvA=="
|
||||
},
|
||||
"Nerdbank.GitVersioning": {
|
||||
"type": "Direct",
|
||||
"requested": "[3.6.133, 3.6.133]",
|
||||
"resolved": "3.6.133",
|
||||
"contentHash": "VZWMd5YAeDxpjWjAP/X6bAxnRMiEf6tES/ITN0X5CHJgkWLLeHGmEALivmTAfYM6P+P/3Szy6VCITUAkqjcHVw=="
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,14 +16,13 @@
|
|||
<repository type="git" url="https://github.com/nanoframework/nanoFramework.WebServer" commit="$commit$" />
|
||||
<copyright>Copyright (c) .NET Foundation and Contributors</copyright>
|
||||
<description>This is a simple multithread WebServer supporting simple controller and event based calls.
|
||||
Perfect for .NET nanoFramework REST API based project. Support all type of Http Methods.
|
||||
Perfect for simple embedded web pages, with Support of file on a storage (USB, SD Card, in Memory).
|
||||
Supports both HTTPS and HTTP.</description>
|
||||
Perfect for .NET nanoFramework REST API based project. Supports both HTTPS and HTTP.
|
||||
If serving files from local storage is a requirement, please use instead the 'nanoFramework.WebServer.FileSystem' nuget.
|
||||
</description>
|
||||
<tags>http https webserver net netmf nf nanoframework</tags>
|
||||
<dependencies>
|
||||
<dependency id="nanoFramework.CoreLibrary" version="1.14.2" />
|
||||
<dependency id="nanoFramework.System.Net.Http.Server" version="1.5.104" />
|
||||
<dependency id="nanoFramework.Windows.Storage" version="1.5.33" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
<files>
|
||||
|
|
|
@ -11,6 +11,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
|||
version.json = version.json
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{11A8DD76-328B-46DF-9F39-F559912D0360}") = "nanoFramework.WebServer.FileSystem", "nanoFramework.WebServer.FileSystem\nanoFramework.WebServer.FileSystem.nfproj", "{9D8A2D18-8036-4880-B46B-D5218247257D}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
@ -23,6 +25,12 @@ Global
|
|||
{87AAA5FE-CBB6-497F-97B7-7AF21B9A0C4E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{87AAA5FE-CBB6-497F-97B7-7AF21B9A0C4E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{87AAA5FE-CBB6-497F-97B7-7AF21B9A0C4E}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||
{9D8A2D18-8036-4880-B46B-D5218247257D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9D8A2D18-8036-4880-B46B-D5218247257D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9D8A2D18-8036-4880-B46B-D5218247257D}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
|
||||
{9D8A2D18-8036-4880-B46B-D5218247257D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9D8A2D18-8036-4880-B46B-D5218247257D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9D8A2D18-8036-4880-B46B-D5218247257D}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
|
@ -16,8 +16,3 @@ using System.Runtime.InteropServices;
|
|||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// This attribute is mandatory when building Interop libraries //
|
||||
// update this whenever the native assembly signature changes //
|
||||
[assembly: AssemblyNativeVersion("0.0.0.0")]
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -6,15 +6,15 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Diagnostics;
|
||||
#if FILESYSTEM
|
||||
using System.IO;
|
||||
#endif
|
||||
using System.Net;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Net.Security;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using Windows.Storage;
|
||||
using Windows.Storage.Streams;
|
||||
|
||||
|
||||
namespace nanoFramework.WebServer
|
||||
{
|
||||
|
@ -281,16 +281,16 @@ namespace nanoFramework.WebServer
|
|||
var space = strAuth.IndexOf(' ');
|
||||
if (space < 0)
|
||||
{
|
||||
throw new ArgumentException($"Authentication attribute Basic should be 'Basic:user passowrd'");
|
||||
throw new ArgumentException($"Authentication attribute Basic should be 'Basic:user password'");
|
||||
}
|
||||
|
||||
var user = strAuth.Substring(sep + 1, space - sep - 1);
|
||||
var password = strAuth.Substring(space + 1);
|
||||
authentication = new Authentication(new NetworkCredential(user, password, System.Net.AuthenticationType.Basic));
|
||||
authentication = new Authentication(new NetworkCredential(user, password, (global::System.Net.AuthenticationType)AuthenticationType.Basic));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException($"Authentication attribute Basic should be 'Basic:user passowrd'");
|
||||
throw new ArgumentException($"Authentication attribute Basic should be 'Basic:user password'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -386,7 +386,7 @@ namespace nanoFramework.WebServer
|
|||
Thread.Sleep(100);
|
||||
_serverThread.Abort();
|
||||
_serverThread = null;
|
||||
Debug.WriteLine("Stoped server in thread ");
|
||||
Debug.WriteLine("Stopped server in thread ");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -424,43 +424,42 @@ namespace nanoFramework.WebServer
|
|||
response.StatusCode = (int)code;
|
||||
}
|
||||
|
||||
#if FILESYSTEM
|
||||
/// <summary>
|
||||
/// Return a file from Storage over HTTP response.
|
||||
/// </summary>
|
||||
/// <param name="response"><see cref="HttpListenerResponse"/> to send the content over.</param>
|
||||
/// <param name="strFilePath">The file to send</param>
|
||||
/// <param name="contentType">The type of file, if empty string, then will use auto detection</param>
|
||||
public static void SendFileOverHTTP(HttpListenerResponse response, StorageFile strFilePath, string contentType = "")
|
||||
public static void SendFileOverHTTP(HttpListenerResponse response, string strFilePath, string contentType = "")
|
||||
{
|
||||
contentType = contentType == "" ? GetContentTypeFromFileName(strFilePath.FileType) : contentType;
|
||||
IBuffer readBuffer = FileIO.ReadBuffer(strFilePath);
|
||||
long fileLength = readBuffer.Length;
|
||||
contentType = contentType == string.Empty ? GetContentTypeFromFileName(strFilePath.Substring(strFilePath.LastIndexOf(".") + 1)) : contentType;
|
||||
|
||||
byte[] buf = new byte[MaxSizeBuffer];
|
||||
using FileStream dataReader = new FileStream(strFilePath, FileMode.Open, FileAccess.Read);
|
||||
|
||||
long fileLength = dataReader.Length;
|
||||
response.ContentType = contentType;
|
||||
response.ContentLength64 = fileLength;
|
||||
response.SendChunked = true;
|
||||
// Now loops sending all the data.
|
||||
|
||||
byte[] buf = new byte[MaxSizeBuffer];
|
||||
using (DataReader dataReader = DataReader.FromBuffer(readBuffer))
|
||||
for (long bytesSent = 0; bytesSent < fileLength;)
|
||||
{
|
||||
for (long bytesSent = 0; bytesSent < fileLength;)
|
||||
{
|
||||
// Determines amount of data left.
|
||||
long bytesToRead = fileLength - bytesSent;
|
||||
bytesToRead = bytesToRead < MaxSizeBuffer ? bytesToRead : MaxSizeBuffer;
|
||||
// Determines amount of data left.
|
||||
long bytesToRead = fileLength - bytesSent;
|
||||
bytesToRead = bytesToRead < MaxSizeBuffer ? bytesToRead : MaxSizeBuffer;
|
||||
|
||||
// Reads the data.
|
||||
dataReader.ReadBytes(buf);
|
||||
// Reads the data.
|
||||
dataReader.Read(buf, 0,(int) bytesToRead);
|
||||
|
||||
// Writes data to browser
|
||||
response.OutputStream.Write(buf, 0, (int)bytesToRead);
|
||||
// Writes data to browser
|
||||
response.OutputStream.Write(buf, 0, (int)bytesToRead);
|
||||
|
||||
// Updates bytes read.
|
||||
bytesSent += bytesToRead;
|
||||
}
|
||||
// Updates bytes read.
|
||||
bytesSent += bytesToRead;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Send file content over HTTP response.
|
||||
|
@ -627,8 +626,24 @@ namespace nanoFramework.WebServer
|
|||
}
|
||||
else
|
||||
{
|
||||
context.Response.Close();
|
||||
context.Close();
|
||||
try
|
||||
{
|
||||
context.Response.Close();
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Nothing on purpose
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
context.Close();
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Nothing on purpose
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}).Start();
|
||||
|
@ -755,6 +770,6 @@ namespace nanoFramework.WebServer
|
|||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
<SignAssembly>true</SignAssembly>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<AssemblyOriginatorKeyFile>key.snk</AssemblyOriginatorKeyFile>
|
||||
<AssemblyOriginatorKeyFile>..\key.snk</AssemblyOriginatorKeyFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<DelaySign>false</DelaySign>
|
||||
|
@ -44,7 +44,7 @@
|
|||
<Compile Include="RouteAttribute.cs" />
|
||||
<Compile Include="UrlParameter.cs" />
|
||||
<Compile Include="WebServer.cs" />
|
||||
<None Include="key.snk" />
|
||||
<None Include="..\key.snk" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="mscorlib, Version=1.14.3.0, Culture=neutral, PublicKeyToken=c07d481e9758c731">
|
||||
|
@ -79,14 +79,6 @@
|
|||
<HintPath>..\packages\nanoFramework.System.Threading.1.1.19\lib\System.Threading.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Windows.Storage, Version=1.5.33.0, Culture=neutral, PublicKeyToken=c07d481e9758c731">
|
||||
<HintPath>..\packages\nanoFramework.Windows.Storage.1.5.33\lib\Windows.Storage.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Windows.Storage.Streams, Version=1.14.24.46541, Culture=neutral, PublicKeyToken=c07d481e9758c731">
|
||||
<HintPath>..\packages\nanoFramework.Windows.Storage.Streams.1.14.24\lib\Windows.Storage.Streams.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
|
|
|
@ -8,7 +8,5 @@
|
|||
<package id="nanoFramework.System.Net.Http.Server" version="1.5.104" targetFramework="netnano1.0" />
|
||||
<package id="nanoFramework.System.Text" version="1.2.37" targetFramework="netnano1.0" />
|
||||
<package id="nanoFramework.System.Threading" version="1.1.19" targetFramework="netnano1.0" />
|
||||
<package id="nanoFramework.Windows.Storage" version="1.5.33" targetFramework="netnano1.0" />
|
||||
<package id="nanoFramework.Windows.Storage.Streams" version="1.14.24" targetFramework="netnano1.0" />
|
||||
<package id="Nerdbank.GitVersioning" version="3.6.133" developmentDependency="true" targetFramework="netnano1.0" />
|
||||
</packages>
|
|
@ -50,18 +50,6 @@
|
|||
"resolved": "1.1.19",
|
||||
"contentHash": "HjnY0DNoFnU+t1GiH8Wgf7pJCD9yMOcLVtAZXVAhstMKisVN/MDj9TvfXxZScRIz7ZDoZYUnb+Ixfl6rqyppvA=="
|
||||
},
|
||||
"nanoFramework.Windows.Storage": {
|
||||
"type": "Direct",
|
||||
"requested": "[1.5.33, 1.5.33]",
|
||||
"resolved": "1.5.33",
|
||||
"contentHash": "9BDmxivx3h/2MfoXcTAUYhZny6iaDN9DwAngx7OrQNvXFgzdbOTMTB17Qcy0iA9EUqTr6HG8TuE2tv2loyNeIA=="
|
||||
},
|
||||
"nanoFramework.Windows.Storage.Streams": {
|
||||
"type": "Direct",
|
||||
"requested": "[1.14.24, 1.14.24]",
|
||||
"resolved": "1.14.24",
|
||||
"contentHash": "dApgYplMFRUTp7izZxvduXgl9B7oqVPqqagkYXFf6cRJRC3Og0y2JZTVJdhGPW/ud0U0+rvjqXOU+1CtEzv88A=="
|
||||
},
|
||||
"Nerdbank.GitVersioning": {
|
||||
"type": "Direct",
|
||||
"requested": "[3.6.133, 3.6.133]",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json",
|
||||
"version": "1.1",
|
||||
"version": "1.2",
|
||||
"assemblyVersion": {
|
||||
"precision": "minor"
|
||||
},
|
||||
|
|
Загрузка…
Ссылка в новой задаче