REST client API: Initial checkin (SPRNET-1345)
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 10.00
|
||||
# Visual Studio 2008
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Spring.Core.2008", "..\..\..\src\Spring\Spring.Core\Spring.Core.2008.csproj", "{710961A3-0DF4-49E4-A26E-F5B9C044AC84}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Spring.Http.2008", "..\..\..\src\Spring\Spring.Http\Spring.Http.2008.csproj", "{FAC04F79-4B1F-1D13-B30F-00EE04EC0FBC}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Spring.Http.Tests.2008", "..\..\..\test\Spring\Spring.Http.Tests\Spring.Http.Tests.2008.csproj", "{F04CEE18-3897-A399-46BF-459437475B21}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Spring.RestQuickStart.2008", "src\Spring.RestQuickStart\Spring.RestQuickStart.2008.csproj", "{5B47D309-31C9-4282-86E2-11FC63DFF55B}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{710961A3-0DF4-49E4-A26E-F5B9C044AC84}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{710961A3-0DF4-49E4-A26E-F5B9C044AC84}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{710961A3-0DF4-49E4-A26E-F5B9C044AC84}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{710961A3-0DF4-49E4-A26E-F5B9C044AC84}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{FAC04F79-4B1F-1D13-B30F-00EE04EC0FBC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FAC04F79-4B1F-1D13-B30F-00EE04EC0FBC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FAC04F79-4B1F-1D13-B30F-00EE04EC0FBC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FAC04F79-4B1F-1D13-B30F-00EE04EC0FBC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{F04CEE18-3897-A399-46BF-459437475B21}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F04CEE18-3897-A399-46BF-459437475B21}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F04CEE18-3897-A399-46BF-459437475B21}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F04CEE18-3897-A399-46BF-459437475B21}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{5B47D309-31C9-4282-86E2-11FC63DFF55B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{5B47D309-31C9-4282-86E2-11FC63DFF55B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{5B47D309-31C9-4282-86E2-11FC63DFF55B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{5B47D309-31C9-4282-86E2-11FC63DFF55B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
NAntAddinLastFileName = Spring.build
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,40 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 11.00
|
||||
# Visual Studio 2010
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Spring.Core.2010", "..\..\..\src\Spring\Spring.Core\Spring.Core.2010.csproj", "{710961A3-0DF4-49E4-A26E-F5B9C044AC84}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Spring.Http.2010", "..\..\..\src\Spring\Spring.Http\Spring.Http.2010.csproj", "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Spring.Http.Tests.2010", "..\..\..\test\Spring\Spring.Http.Tests\Spring.Http.Tests.2010.csproj", "{4594CEE7-3897-A3BF-9946-5B4374F01821}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Spring.RestQuickStart.2010", "src\Spring.RestQuickStart\Spring.RestQuickStart.2010.csproj", "{5B47D309-31C9-4282-86E2-11FC63DFF55B}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{710961A3-0DF4-49E4-A26E-F5B9C044AC84}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{710961A3-0DF4-49E4-A26E-F5B9C044AC84}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{710961A3-0DF4-49E4-A26E-F5B9C044AC84}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{710961A3-0DF4-49E4-A26E-F5B9C044AC84}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4594CEE7-3897-A3BF-9946-5B4374F01821}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4594CEE7-3897-A3BF-9946-5B4374F01821}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4594CEE7-3897-A3BF-9946-5B4374F01821}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4594CEE7-3897-A3BF-9946-5B4374F01821}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{5B47D309-31C9-4282-86E2-11FC63DFF55B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{5B47D309-31C9-4282-86E2-11FC63DFF55B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{5B47D309-31C9-4282-86E2-11FC63DFF55B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{5B47D309-31C9-4282-86E2-11FC63DFF55B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
NAntAddinLastFileName = Spring.build
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
|
||||
using Spring.Http.Rest;
|
||||
|
||||
namespace Spring.RestQuickStart
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
try
|
||||
{
|
||||
RestTemplate rt = new RestTemplate("http://twitter.com");
|
||||
string result = rt.GetForObject<string>("/statuses/user_timeline.xml?id={id}", "lancearmstrong");
|
||||
|
||||
Console.WriteLine(result);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Console.WriteLine("--- hit <return> to quit ---");
|
||||
Console.ReadLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>9.0.30729</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{5B47D309-31C9-4282-86E2-11FC63DFF55B}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Spring.RestQuickStart</RootNamespace>
|
||||
<AssemblyName>Spring.RestQuickStart</AssemblyName>
|
||||
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Xml.Linq">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Program.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\..\src\Spring\Spring.Core\Spring.Core.2008.csproj">
|
||||
<Project>{710961A3-0DF4-49E4-A26E-F5B9C044AC84}</Project>
|
||||
<Name>Spring.Core.2008</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\..\..\src\Spring\Spring.Http\Spring.Http.2008.csproj">
|
||||
<Project>{FAC04F79-4B1F-1D13-B30F-00EE04EC0FBC}</Project>
|
||||
<Name>Spring.Http.2008</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
@@ -0,0 +1,80 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>9.0.30729</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{5B47D309-31C9-4282-86E2-11FC63DFF55B}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Spring.RestQuickStart</RootNamespace>
|
||||
<AssemblyName>Spring.RestQuickStart</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<FileUpgradeFlags>
|
||||
</FileUpgradeFlags>
|
||||
<OldToolsVersion>3.5</OldToolsVersion>
|
||||
<UpgradeBackupLocation />
|
||||
<TargetFrameworkProfile />
|
||||
<PublishUrl>publish\</PublishUrl>
|
||||
<Install>true</Install>
|
||||
<InstallFrom>Disk</InstallFrom>
|
||||
<UpdateEnabled>false</UpdateEnabled>
|
||||
<UpdateMode>Foreground</UpdateMode>
|
||||
<UpdateInterval>7</UpdateInterval>
|
||||
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
|
||||
<UpdatePeriodically>false</UpdatePeriodically>
|
||||
<UpdateRequired>false</UpdateRequired>
|
||||
<MapFileExtensions>true</MapFileExtensions>
|
||||
<ApplicationRevision>0</ApplicationRevision>
|
||||
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
|
||||
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||
<UseApplicationTrust>false</UseApplicationTrust>
|
||||
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Xml.Linq">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Program.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\..\src\Spring\Spring.Core\Spring.Core.2010.csproj">
|
||||
<Project>{710961A3-0DF4-49E4-A26E-F5B9C044AC84}</Project>
|
||||
<Name>Spring.Core.2010</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\..\..\src\Spring\Spring.Http\Spring.Http.2010.csproj">
|
||||
<Project>{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</Project>
|
||||
<Name>Spring.Http.2010</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
5
src/Spring/Spring.Http/AssemblyInfo.cs
Normal file
5
src/Spring/Spring.Http/AssemblyInfo.cs
Normal file
@@ -0,0 +1,5 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
[assembly: AssemblyTitle("Spring.Http")]
|
||||
[assembly: AssemblyDescription("Interfaces and classes that provide REST client API in Spring.Net")]
|
||||
@@ -0,0 +1,224 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Spring.Util;
|
||||
|
||||
namespace Spring.Http.Converters
|
||||
{
|
||||
/**
|
||||
* Abstract base class for most {@link HttpMessageConverter} implementations.
|
||||
*
|
||||
* <p>This base class adds support for setting supported {@code MediaTypes}, through the
|
||||
* {@link #setSupportedMediaTypes(List) supportedMediaTypes} bean property. It also adds
|
||||
* support for {@code Content-Type} and {@code Content-Length} when writing to output messages.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
*/
|
||||
public abstract class AbstractHttpMessageConverter : IHttpMessageConverter
|
||||
{
|
||||
#region Logging
|
||||
|
||||
private static readonly Common.Logging.ILog LOG = Common.Logging.LogManager.GetLogger(typeof(AbstractHttpMessageConverter));
|
||||
|
||||
#endregion
|
||||
|
||||
private IList<MediaType> _supportedMediaTypes = new List<MediaType>();
|
||||
|
||||
/**
|
||||
* Set the list of {@link MediaType} objects supported by this converter.
|
||||
*/
|
||||
public IList<MediaType> SupportedMediaTypes
|
||||
{
|
||||
get { return _supportedMediaTypes; }
|
||||
set { _supportedMediaTypes = value; }
|
||||
}
|
||||
|
||||
#region Constructor(s)
|
||||
|
||||
/**
|
||||
* Construct an {@code AbstractHttpMessageConverter} with no supported media types.
|
||||
* @see #setSupportedMediaTypes
|
||||
*/
|
||||
protected AbstractHttpMessageConverter()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an {@code AbstractHttpMessageConverter} with multiple supported media type.
|
||||
* @param supportedMediaTypes the supported media types
|
||||
*/
|
||||
protected AbstractHttpMessageConverter(params MediaType[] supportedMediaTypes)
|
||||
{
|
||||
this._supportedMediaTypes = new List<MediaType>(supportedMediaTypes);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IHttpMessageConverter Membres
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* <p>This implementation checks if the given class is {@linkplain #supports(Class) supported},
|
||||
* and if the {@linkplain #getSupportedMediaTypes() supported media types}
|
||||
* {@linkplain MediaType#includes(MediaType) include} the given media type.
|
||||
*/
|
||||
public bool CanRead(Type type, MediaType mediaType)
|
||||
{
|
||||
return Supports(type) && CanRead(mediaType);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* <p>This implementation checks if the given class is {@linkplain #supports(Class) supported},
|
||||
* and if the {@linkplain #getSupportedMediaTypes() supported media types}
|
||||
* {@linkplain MediaType#includes(MediaType) include} the given media type.
|
||||
*/
|
||||
public bool CanWrite(Type type, MediaType mediaType)
|
||||
{
|
||||
return Supports(type) && CanWrite(mediaType);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* <p>This implementation simple delegates to {@link #readInternal(Class, HttpInputMessage)}.
|
||||
* Future implementations might add some default behavior, however.
|
||||
*/
|
||||
public T Read<T>(HttpWebResponse response) where T : class
|
||||
{
|
||||
return ReadInternal<T>(response);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* <p>This implementation delegates to {@link #getDefaultContentType(Object)} if a content
|
||||
* type was not provided, calls {@link #getContentLength}, and sets the corresponding headers
|
||||
* on the output message. It then calls {@link #writeInternal}.
|
||||
*/
|
||||
public void Write(object content, MediaType mediaType, HttpWebRequest request)
|
||||
{
|
||||
if (!StringUtils.HasText(request.Headers[HttpRequestHeader.ContentType]))
|
||||
{
|
||||
if (mediaType == null || mediaType.IsWildcardType || mediaType.IsWildcardSubtype)
|
||||
{
|
||||
mediaType = GetDefaultContentType(content.GetType());
|
||||
}
|
||||
if (mediaType != null)
|
||||
{
|
||||
request.ContentType = mediaType.ToString();
|
||||
}
|
||||
}
|
||||
WriteInternal(content, request);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/**
|
||||
* Returns true if any of the {@linkplain #setSupportedMediaTypes(List) supported media types}
|
||||
* include the given media type.
|
||||
* @param mediaType the media type to read, can be {@code null} if not specified. Typically the value of a
|
||||
* {@code Content-Type} header.
|
||||
* @return true if the supported media types include the media type, or if the media type is {@code null}
|
||||
*/
|
||||
protected bool CanRead(MediaType mediaType)
|
||||
{
|
||||
if (mediaType == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
foreach(MediaType supportedMediaType in this._supportedMediaTypes)
|
||||
{
|
||||
if (supportedMediaType.Includes(mediaType))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given media type includes any of the
|
||||
* {@linkplain #setSupportedMediaTypes(List) supported media types}.
|
||||
* @param mediaType the media type to write, can be {@code null} if not specified. Typically the value of an
|
||||
* {@code Accept} header.
|
||||
* @return true if the supported media types are compatible with the media type, or if the media type is {@code null}
|
||||
*/
|
||||
protected bool CanWrite(MediaType mediaType)
|
||||
{
|
||||
if (mediaType == null || mediaType.Equals(MediaType.ALL))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
foreach(MediaType supportedMediaType in this._supportedMediaTypes)
|
||||
{
|
||||
if (supportedMediaType.IsCompatibleWith(mediaType))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default content type for the given type. Called when {@link #write}
|
||||
* is invoked without a specified content type parameter.
|
||||
* <p>By default, this returns the first element of the
|
||||
* {@link #setSupportedMediaTypes(List) supportedMediaTypes} property, if any.
|
||||
* Can be overridden in subclasses.
|
||||
* @param t the type to return the content type for
|
||||
* @return the content type, or <code>null</code> if not known
|
||||
*/
|
||||
protected virtual MediaType GetDefaultContentType(Type type)
|
||||
{
|
||||
return (this._supportedMediaTypes.Count > 0 ? this._supportedMediaTypes[0] : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the given class is supported by this converter.
|
||||
* @param clazz the class to test for support
|
||||
* @return <code>true</code> if supported; <code>false</code> otherwise
|
||||
*/
|
||||
protected abstract bool Supports(Type type);
|
||||
|
||||
/**
|
||||
* Abstract template method that reads the actualy object. Invoked from {@link #read}.
|
||||
* @param clazz the type of object to return
|
||||
* @param inputMessage the HTTP input message to read from
|
||||
* @return the converted object
|
||||
* @throws IOException in case of I/O errors
|
||||
* @throws HttpMessageNotReadableException in case of conversion errors
|
||||
*/
|
||||
protected abstract T ReadInternal<T>(HttpWebResponse response) where T : class;
|
||||
|
||||
/**
|
||||
* Abstract template method that writes the actual body. Invoked from {@link #write}.
|
||||
* @param t the object to write to the output message
|
||||
* @param outputMessage the message to write to
|
||||
* @throws IOException in case of I/O errors
|
||||
* @throws HttpMessageNotWritableException in case of conversion errors
|
||||
*/
|
||||
protected abstract void WriteInternal(object content, HttpWebRequest request);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
|
||||
namespace Spring.Http.Converters
|
||||
{
|
||||
/**
|
||||
* Implementation of {@link HttpMessageConverter} that can read and write byte arrays.
|
||||
*
|
||||
* <p>By default, this converter supports all media types (<code>*/*</code>), and writes with a {@code
|
||||
* Content-Type} of {@code application/octet-stream}. This can be overridden by setting the {@link
|
||||
* #setSupportedMediaTypes(java.util.List) supportedMediaTypes} property.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 3.0
|
||||
*/
|
||||
public class ByteArrayHttpMessageConverter : AbstractHttpMessageConverter
|
||||
{
|
||||
/** Creates a new instance of the {@code ByteArrayHttpMessageConverter}. */
|
||||
public ByteArrayHttpMessageConverter() :
|
||||
base(new MediaType("application", "octet-stream"), MediaType.ALL)
|
||||
{
|
||||
}
|
||||
|
||||
protected override bool Supports(Type type)
|
||||
{
|
||||
return type.Equals(typeof(byte[]));
|
||||
}
|
||||
|
||||
protected override T ReadInternal<T>(HttpWebResponse response)
|
||||
{
|
||||
// Get the response stream
|
||||
using (BinaryReader reader = new BinaryReader(response.GetResponseStream()))
|
||||
{
|
||||
return reader.ReadBytes((int)response.ContentLength) as T;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void WriteInternal(object content, HttpWebRequest request)
|
||||
{
|
||||
// Create a byte array of the data we want to send
|
||||
byte[] byteData = content as byte[];
|
||||
|
||||
// Set the content length in the request headers
|
||||
request.ContentLength = byteData.Length;
|
||||
|
||||
// Write data
|
||||
using (Stream postStream = request.GetRequestStream())
|
||||
{
|
||||
postStream.Write(byteData, 0, byteData.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
#if NET_3_5
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Xml;
|
||||
using System.ServiceModel.Syndication;
|
||||
|
||||
using Spring.Http.Converters.Xml;
|
||||
|
||||
namespace Spring.Http.Converters.Feed
|
||||
{
|
||||
public abstract class AbstractFeedHttpMessageConverter : AbstractXmlHttpMessageConverter
|
||||
{
|
||||
/**
|
||||
* Construct an {@code AbstractHttpMessageConverter} with multiple supported media type.
|
||||
* @param supportedMediaTypes the supported media types
|
||||
*/
|
||||
protected AbstractFeedHttpMessageConverter(params MediaType[] supportedMediaTypes) :
|
||||
base(supportedMediaTypes)
|
||||
{
|
||||
}
|
||||
|
||||
protected override bool Supports(Type type)
|
||||
{
|
||||
return type.Equals(typeof(SyndicationFeed));
|
||||
}
|
||||
|
||||
protected override T ReadXml<T>(XmlReader xmlReader, HttpWebResponse response)
|
||||
{
|
||||
return SyndicationFeed.Load(xmlReader) as T;
|
||||
}
|
||||
|
||||
protected override XmlReaderSettings GetDefaultXmlReaderSettings()
|
||||
{
|
||||
XmlReaderSettings settings = new XmlReaderSettings();
|
||||
settings.CloseInput = true;
|
||||
settings.IgnoreProcessingInstructions = true;
|
||||
settings.ProhibitDtd = false;
|
||||
settings.XmlResolver = null;
|
||||
return settings;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,43 @@
|
||||
#if NET_3_5
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Xml;
|
||||
using System.ServiceModel.Syndication;
|
||||
|
||||
namespace Spring.Http.Converters.Feed
|
||||
{
|
||||
public class Atom10FeedHttpMessageConverter : AbstractFeedHttpMessageConverter
|
||||
{
|
||||
public Atom10FeedHttpMessageConverter() :
|
||||
base(new MediaType("application", "atom+xml"))
|
||||
{
|
||||
}
|
||||
|
||||
protected override void WriteXml(XmlWriter xmlWriter, object content, HttpWebRequest request)
|
||||
{
|
||||
SyndicationFeed rssFeed = content as SyndicationFeed;
|
||||
rssFeed.SaveAsAtom10(xmlWriter);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,43 @@
|
||||
#if NET_3_5
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Xml;
|
||||
using System.ServiceModel.Syndication;
|
||||
|
||||
namespace Spring.Http.Converters.Feed
|
||||
{
|
||||
public class Rss20FeedHttpMessageConverter : AbstractFeedHttpMessageConverter
|
||||
{
|
||||
public Rss20FeedHttpMessageConverter() :
|
||||
base(new MediaType("application", "rss+xml"))
|
||||
{
|
||||
}
|
||||
|
||||
protected override void WriteXml(XmlWriter xmlWriter, object content, HttpWebRequest request)
|
||||
{
|
||||
SyndicationFeed rssFeed = content as SyndicationFeed;
|
||||
rssFeed.SaveAsRss20(xmlWriter);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,85 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Spring.Http.Converters
|
||||
{
|
||||
/**
|
||||
* Strategy interface that specifies a converter that can convert from and to HTTP requests and responses.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
*/
|
||||
public interface IHttpMessageConverter
|
||||
{
|
||||
/**
|
||||
* Indicates whether the given class can be read by this converter.
|
||||
* @param clazz the class to test for readability
|
||||
* @param mediaType the media type to read, can be {@code null} if not specified. Typically the value of a
|
||||
* {@code Content-Type} header.
|
||||
* @return {@code true} if readable; {@code false} otherwise
|
||||
*/
|
||||
bool CanRead(Type type, MediaType mediaType);
|
||||
|
||||
/**
|
||||
* Indicates whether the given class can be written by this converter.
|
||||
* @param clazz the class to test for writability
|
||||
* @param mediaType the media type to write, can be {@code null} if not specified. Typically the value of an
|
||||
* {@code Accept} header.
|
||||
* @return {@code true} if writable; {@code false} otherwise
|
||||
*/
|
||||
bool CanWrite(Type type, MediaType mediaType);
|
||||
|
||||
/**
|
||||
* Return the list of {@link MediaType} objects supported by this converter.
|
||||
* @return the list of supported media types
|
||||
*/
|
||||
IList<MediaType> SupportedMediaTypes { get; }
|
||||
|
||||
/**
|
||||
* Read an object of the given type form the given input message, and returns it.
|
||||
* @param clazz the type of object to return. This type must have previously been passed to the
|
||||
* {@link #canRead canRead} method of this interface, which must have returned {@code true}.
|
||||
* @param inputMessage the HTTP input message to read from
|
||||
* @return the converted object
|
||||
* @throws IOException in case of I/O errors
|
||||
* @throws HttpMessageNotReadableException in case of conversion errors
|
||||
*/
|
||||
T Read<T>(HttpWebResponse response) where T : class;
|
||||
|
||||
/**
|
||||
* Write an given object to the given output message.
|
||||
* @param t the object to write to the output message. The type of this object must have previously been
|
||||
* passed to the {@link #canWrite canWrite} method of this interface, which must have returned {@code true}.
|
||||
* @param contentType the content type to use when writing. May be {@code null} to indicate that the
|
||||
* default content type of the converter must be used. If not {@code null}, this media type must have
|
||||
* previously been passed to the {@link #canWrite canWrite} method of this interface, which must have
|
||||
* returned {@code true}.
|
||||
* @param outputMessage the message to write to
|
||||
* @throws IOException in case of I/O errors
|
||||
* @throws HttpMessageNotWritableException in case of conversion errors
|
||||
*/
|
||||
void Write(object content, MediaType mediaType, HttpWebRequest request);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
#if NET_3_5
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Xml;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Runtime.Serialization.Json;
|
||||
|
||||
using Spring.Util;
|
||||
|
||||
namespace Spring.Http.Converters.Json
|
||||
{
|
||||
// TODO : Support for known types, etc...
|
||||
public class JsonHttpMessageConverter : AbstractHttpMessageConverter
|
||||
{
|
||||
public static readonly Encoding DEFAULT_CHARSET = Encoding.UTF8;
|
||||
|
||||
public JsonHttpMessageConverter() :
|
||||
base(new MediaType("application", "json"))
|
||||
{
|
||||
}
|
||||
|
||||
protected override bool Supports(Type type)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override T ReadInternal<T>(HttpWebResponse response)
|
||||
{
|
||||
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));
|
||||
using (Stream stream = response.GetResponseStream())
|
||||
{
|
||||
return (T)serializer.ReadObject(stream) as T;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void WriteInternal(object content, HttpWebRequest request)
|
||||
{
|
||||
// Get the request encoding
|
||||
MediaType mediaType = MediaType.ParseMediaType(request.Headers[HttpRequestHeader.ContentType]);
|
||||
Encoding encoding;
|
||||
if (mediaType == null || String.IsNullOrEmpty(mediaType.CharSet))
|
||||
{
|
||||
encoding = DEFAULT_CHARSET;
|
||||
}
|
||||
else
|
||||
{
|
||||
encoding = Encoding.GetEncoding(mediaType.CharSet);
|
||||
}
|
||||
|
||||
DataContractJsonSerializer serializer = new DataContractJsonSerializer(content.GetType());
|
||||
|
||||
// Write data
|
||||
using (Stream postStream = request.GetRequestStream())
|
||||
{
|
||||
using (XmlDictionaryWriter jsonWriter = JsonReaderWriterFactory.CreateJsonWriter(postStream, encoding, false))
|
||||
{
|
||||
serializer.WriteObject(jsonWriter, content);
|
||||
jsonWriter.Flush();
|
||||
}
|
||||
postStream.Flush();
|
||||
|
||||
// Set the content length in the request headers
|
||||
request.ContentLength = postStream.Length;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,99 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
|
||||
namespace Spring.Http.Converters
|
||||
{
|
||||
/**
|
||||
* Implementation of {@link HttpMessageConverter} that can read and write strings.
|
||||
*
|
||||
* <p>By default, this converter supports all media types (<code>*/*</code>), and writes with a {@code
|
||||
* Content-Type} of {@code text/plain}. This can be overridden by setting the {@link
|
||||
* #setSupportedMediaTypes(java.util.List) supportedMediaTypes} property.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 3.0
|
||||
*/
|
||||
public class StringHttpMessageConverter : AbstractHttpMessageConverter
|
||||
{
|
||||
public static readonly Encoding DEFAULT_CHARSET = Encoding.GetEncoding("ISO-8859-1");
|
||||
|
||||
public StringHttpMessageConverter() :
|
||||
base(new MediaType("text", "plain", "ISO-8859-1"), MediaType.ALL)
|
||||
{
|
||||
}
|
||||
|
||||
protected override bool Supports(Type type)
|
||||
{
|
||||
return type.Equals(typeof(string));
|
||||
}
|
||||
|
||||
protected override T ReadInternal<T>(HttpWebResponse response)
|
||||
{
|
||||
// Get the response encoding
|
||||
Encoding encoding;
|
||||
if (String.IsNullOrEmpty(response.CharacterSet))
|
||||
{
|
||||
encoding = DEFAULT_CHARSET;
|
||||
}
|
||||
else
|
||||
{
|
||||
encoding = Encoding.GetEncoding(response.CharacterSet);
|
||||
}
|
||||
|
||||
// Get the response stream
|
||||
using (StreamReader reader = new StreamReader(response.GetResponseStream(), encoding))
|
||||
{
|
||||
return reader.ReadToEnd() as T;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void WriteInternal(object content, HttpWebRequest request)
|
||||
{
|
||||
// Get the request encoding
|
||||
MediaType mediaType = MediaType.ParseMediaType(request.Headers[HttpRequestHeader.ContentType]);
|
||||
Encoding encoding;
|
||||
if (mediaType == null || String.IsNullOrEmpty(mediaType.CharSet))
|
||||
{
|
||||
encoding = DEFAULT_CHARSET;
|
||||
}
|
||||
else
|
||||
{
|
||||
encoding = Encoding.GetEncoding(mediaType.CharSet);
|
||||
}
|
||||
|
||||
// Create a byte array of the data we want to send
|
||||
byte[] byteData = encoding.GetBytes(content as string);
|
||||
|
||||
// Set the content length in the request headers
|
||||
request.ContentLength = byteData.Length;
|
||||
|
||||
// Write data
|
||||
using (Stream postStream = request.GetRequestStream())
|
||||
{
|
||||
postStream.Write(byteData, 0, byteData.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Xml;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
|
||||
namespace Spring.Http.Converters.Xml
|
||||
{
|
||||
public abstract class AbstractXmlHttpMessageConverter : AbstractHttpMessageConverter
|
||||
{
|
||||
public static readonly Encoding DEFAULT_CHARSET = Encoding.UTF8;
|
||||
|
||||
private XmlReaderSettings _xmlReaderSettings;
|
||||
|
||||
public XmlReaderSettings XmlReaderSettings
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_xmlReaderSettings == null)
|
||||
{
|
||||
_xmlReaderSettings = this.GetDefaultXmlReaderSettings();
|
||||
}
|
||||
return _xmlReaderSettings;
|
||||
}
|
||||
set { _xmlReaderSettings = value; }
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an {@code AbstractHttpMessageConverter} with multiple supported media type.
|
||||
* @param supportedMediaTypes the supported media types
|
||||
*/
|
||||
protected AbstractXmlHttpMessageConverter(params MediaType[] supportedMediaTypes) :
|
||||
base(supportedMediaTypes)
|
||||
{
|
||||
}
|
||||
|
||||
protected override T ReadInternal<T>(HttpWebResponse response)
|
||||
{
|
||||
using (Stream stream = response.GetResponseStream())
|
||||
{
|
||||
using (XmlReader xmlReader = XmlReader.Create(stream, this.XmlReaderSettings))
|
||||
{
|
||||
return ReadXml<T>(xmlReader, response);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void WriteInternal(object content, HttpWebRequest request)
|
||||
{
|
||||
// Get the request encoding
|
||||
MediaType mediaType = MediaType.ParseMediaType(request.Headers[HttpRequestHeader.ContentType]);
|
||||
Encoding encoding;
|
||||
if (mediaType == null || String.IsNullOrEmpty(mediaType.CharSet))
|
||||
{
|
||||
encoding = DEFAULT_CHARSET;
|
||||
}
|
||||
else
|
||||
{
|
||||
encoding = Encoding.GetEncoding(mediaType.CharSet);
|
||||
}
|
||||
|
||||
using (Stream postStream = request.GetRequestStream())
|
||||
{
|
||||
using (XmlTextWriter xmlWriter = new XmlTextWriter(postStream, encoding))
|
||||
{
|
||||
WriteXml(xmlWriter, content, request);
|
||||
xmlWriter.Flush();
|
||||
}
|
||||
|
||||
// TODO : Don't work
|
||||
// Set the content length in the request headers
|
||||
request.ContentLength = postStream.Length;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual XmlReaderSettings GetDefaultXmlReaderSettings()
|
||||
{
|
||||
XmlReaderSettings settings = new XmlReaderSettings();
|
||||
settings.ConformanceLevel = ConformanceLevel.Auto;
|
||||
settings.CloseInput = true;
|
||||
settings.IgnoreProcessingInstructions = true;
|
||||
settings.IgnoreWhitespace = true;
|
||||
return settings;
|
||||
}
|
||||
|
||||
protected abstract T ReadXml<T>(XmlReader xmlReader, HttpWebResponse response) where T : class;
|
||||
|
||||
protected abstract void WriteXml(XmlWriter xmlWriter, object content, HttpWebRequest request);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
#if NET_3_0
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Xml;
|
||||
using System.Text;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
using Spring.Util;
|
||||
|
||||
namespace Spring.Http.Converters.Xml
|
||||
{
|
||||
// TODO : Derive from AbstractXmlHttpMessageConverter ?
|
||||
// TODO : Support for known types, etc...
|
||||
public class DataContractHttpMessageConverter : AbstractHttpMessageConverter
|
||||
{
|
||||
public static readonly Encoding DEFAULT_CHARSET = Encoding.UTF8;
|
||||
|
||||
public DataContractHttpMessageConverter() :
|
||||
base(new MediaType("application", "xml"), new MediaType("text", "xml"), new MediaType("application", "*+xml"))
|
||||
{
|
||||
}
|
||||
|
||||
protected override bool Supports(Type type)
|
||||
{
|
||||
return true;
|
||||
//return (
|
||||
// AttributeUtils.FindAttribute(type, typeof(DataContractAttribute)) != null ||
|
||||
// AttributeUtils.FindAttribute(type, typeof(SerializableAttribute)) != null ||
|
||||
// typeof(ISerializable).IsAssignableFrom(type));
|
||||
}
|
||||
|
||||
protected override T ReadInternal<T>(HttpWebResponse response)
|
||||
{
|
||||
DataContractSerializer serializer = new DataContractSerializer(typeof(T));
|
||||
using (Stream stream = response.GetResponseStream())
|
||||
{
|
||||
return (T)serializer.ReadObject(stream) as T;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void WriteInternal(object content, HttpWebRequest request)
|
||||
{
|
||||
// Get the request encoding
|
||||
MediaType mediaType = MediaType.ParseMediaType(request.Headers[HttpRequestHeader.ContentType]);
|
||||
Encoding encoding;
|
||||
if (mediaType == null || String.IsNullOrEmpty(mediaType.CharSet))
|
||||
{
|
||||
encoding = DEFAULT_CHARSET;
|
||||
}
|
||||
else
|
||||
{
|
||||
encoding = Encoding.GetEncoding(mediaType.CharSet);
|
||||
}
|
||||
|
||||
DataContractSerializer serializer = new DataContractSerializer(content.GetType());
|
||||
|
||||
// Write data
|
||||
using (Stream postStream = request.GetRequestStream())
|
||||
{
|
||||
using (XmlTextWriter xmlWriter = new XmlTextWriter(postStream, encoding))
|
||||
{
|
||||
serializer.WriteObject(xmlWriter, content);
|
||||
xmlWriter.Flush();
|
||||
}
|
||||
|
||||
// Set the content length in the request headers
|
||||
request.ContentLength = postStream.Length;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,54 @@
|
||||
#if NET_3_5
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Xml;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Spring.Http.Converters.Xml
|
||||
{
|
||||
// TODO : Support XElement.Load options
|
||||
public class XElementHttpMessageConverter : AbstractXmlHttpMessageConverter
|
||||
{
|
||||
public XElementHttpMessageConverter() :
|
||||
base(new MediaType("application", "xml"), new MediaType("text", "xml"), new MediaType("application", "*+xml"))
|
||||
{
|
||||
}
|
||||
|
||||
protected override bool Supports(Type type)
|
||||
{
|
||||
return type.Equals(typeof(XElement));
|
||||
}
|
||||
|
||||
protected override T ReadXml<T>(XmlReader xmlReader, HttpWebResponse response)
|
||||
{
|
||||
return XElement.Load(xmlReader) as T;
|
||||
}
|
||||
|
||||
protected override void WriteXml(XmlWriter xmlWriter, object content, HttpWebRequest request)
|
||||
{
|
||||
XElement xElement = content as XElement;
|
||||
xElement.WriteTo(xmlWriter);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,52 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Xml;
|
||||
using System.Net;
|
||||
|
||||
namespace Spring.Http.Converters.Xml
|
||||
{
|
||||
public class XmlDocumentHttpMessageConverter : AbstractXmlHttpMessageConverter
|
||||
{
|
||||
public XmlDocumentHttpMessageConverter() :
|
||||
base(new MediaType("application", "xml"), new MediaType("text", "xml"), new MediaType("application", "*+xml"))
|
||||
{
|
||||
}
|
||||
|
||||
protected override bool Supports(Type type)
|
||||
{
|
||||
return type.Equals(typeof(XmlDocument));
|
||||
}
|
||||
|
||||
protected override T ReadXml<T>(XmlReader xmlReader, HttpWebResponse response)
|
||||
{
|
||||
XmlDocument document = new XmlDocument();
|
||||
document.Load(xmlReader);
|
||||
return document as T;
|
||||
}
|
||||
|
||||
protected override void WriteXml(XmlWriter xmlWriter, object content, HttpWebRequest request)
|
||||
{
|
||||
XmlDocument document = content as XmlDocument;
|
||||
document.WriteTo(xmlWriter);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Xml;
|
||||
using System.Net;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
using Spring.Util;
|
||||
|
||||
namespace Spring.Http.Converters.Xml
|
||||
{
|
||||
// TODO : Support for known types, etc...
|
||||
public class XmlSerializableHttpMessageConverter : AbstractXmlHttpMessageConverter
|
||||
{
|
||||
public XmlSerializableHttpMessageConverter() :
|
||||
base(new MediaType("application", "xml"), new MediaType("text", "xml"), new MediaType("application", "*+xml"))
|
||||
{
|
||||
}
|
||||
|
||||
protected override bool Supports(Type type)
|
||||
{
|
||||
return true;
|
||||
//return (
|
||||
// AttributeUtils.FindAttribute(type, typeof(XmlRootAttribute)) != null ||
|
||||
// AttributeUtils.FindAttribute(type, typeof(XmlTypeAttribute)) != null);
|
||||
}
|
||||
|
||||
protected override T ReadXml<T>(XmlReader xmlReader, HttpWebResponse response)
|
||||
{
|
||||
XmlSerializer serializer = new XmlSerializer(typeof(T));
|
||||
return serializer.Deserialize(xmlReader) as T;
|
||||
}
|
||||
|
||||
protected override void WriteXml(XmlWriter xmlWriter, object content, HttpWebRequest request)
|
||||
{
|
||||
XmlSerializer serializer = new XmlSerializer(content.GetType());
|
||||
serializer.Serialize(xmlWriter, content);
|
||||
}
|
||||
}
|
||||
}
|
||||
116
src/Spring/Spring.Http/Http/DefaultHttpWebRequestFactory.cs
Normal file
116
src/Spring/Spring.Http/Http/DefaultHttpWebRequestFactory.cs
Normal file
@@ -0,0 +1,116 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
|
||||
namespace Spring.Http
|
||||
{
|
||||
/**
|
||||
* Factory for {@link ClientHttpRequest} objects.
|
||||
* Requests are created by the {@link #createRequest(URI, HttpMethod)} method.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 3.0
|
||||
*/
|
||||
public class DefaultHttpWebRequestFactory : IHttpWebRequestFactory
|
||||
{
|
||||
// TODO : Add other properties
|
||||
|
||||
private X509CertificateCollection _clientCertificates;
|
||||
private ICredentials _credentials;
|
||||
private IWebProxy _proxy;
|
||||
private int? _timeout;
|
||||
|
||||
public X509CertificateCollection ClientCertificates
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this._clientCertificates == null)
|
||||
{
|
||||
this._clientCertificates = new X509CertificateCollection();
|
||||
}
|
||||
return this._clientCertificates;
|
||||
}
|
||||
}
|
||||
|
||||
public ICredentials Credentials
|
||||
{
|
||||
get { return _credentials; }
|
||||
set { _credentials = value; }
|
||||
}
|
||||
|
||||
public IWebProxy Proxy
|
||||
{
|
||||
get { return _proxy; }
|
||||
set { _proxy = value; }
|
||||
}
|
||||
|
||||
public int? Timeout
|
||||
{
|
||||
get { return _timeout; }
|
||||
set { _timeout = value; }
|
||||
}
|
||||
|
||||
#region IHttpWebRequestFactory Membres
|
||||
|
||||
/**
|
||||
* Create a new {@link ClientHttpRequest} for the specified URI and HTTP method.
|
||||
* <p>The returned request can be written to, and then executed by calling
|
||||
* {@link ClientHttpRequest#execute()}.
|
||||
* @param uri the URI to create a request for
|
||||
* @param httpMethod the HTTP method to execute
|
||||
* @return the created request
|
||||
* @throws IOException in case of I/O errors
|
||||
*/
|
||||
public HttpWebRequest CreateRequest(Uri uri)
|
||||
{
|
||||
HttpWebRequest request = WebRequest.Create(uri) as HttpWebRequest;
|
||||
|
||||
if (this._clientCertificates != null)
|
||||
{
|
||||
foreach (X509Certificate2 certificate in this._clientCertificates)
|
||||
{
|
||||
request.ClientCertificates.Add(certificate);
|
||||
}
|
||||
}
|
||||
|
||||
if (this._credentials != null)
|
||||
{
|
||||
request.Credentials = this._credentials;
|
||||
}
|
||||
|
||||
if (this._proxy != null)
|
||||
{
|
||||
request.Proxy = this._proxy;
|
||||
}
|
||||
|
||||
if (this._timeout != null)
|
||||
{
|
||||
request.Timeout = this._timeout.Value;
|
||||
}
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
44
src/Spring/Spring.Http/Http/HttpMethod.cs
Normal file
44
src/Spring/Spring.Http/Http/HttpMethod.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
|
||||
namespace Spring.Http
|
||||
{
|
||||
/**
|
||||
* Java 5 enumeration of HTTP request methods. Intended for use
|
||||
* with {@link org.springframework.http.client.ClientHttpRequest}
|
||||
* and {@link org.springframework.web.client.RestTemplate}.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 3.0
|
||||
*/
|
||||
public enum HttpMethod
|
||||
{
|
||||
OPTIONS,
|
||||
GET,
|
||||
HEAD,
|
||||
POST,
|
||||
PUT,
|
||||
DELETE,
|
||||
TRACE,
|
||||
CONNECT
|
||||
}
|
||||
}
|
||||
134
src/Spring/Spring.Http/Http/HttpRequestMessage.cs
Normal file
134
src/Spring/Spring.Http/Http/HttpRequestMessage.cs
Normal file
@@ -0,0 +1,134 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System.Net;
|
||||
|
||||
namespace Spring.Http
|
||||
{
|
||||
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5
|
||||
public class HttpRequestMessage
|
||||
{
|
||||
//private string requestUri;
|
||||
//private string httpVersion;
|
||||
private HttpMethod method;
|
||||
private WebHeaderCollection headers;
|
||||
private object body;
|
||||
|
||||
//public string RequestUri
|
||||
//{
|
||||
// get { return this.requestUri; }
|
||||
// set { this.requestUri = value; }
|
||||
//}
|
||||
|
||||
//public string HttpVersion
|
||||
//{
|
||||
// get { return httpVersion; }
|
||||
// set { httpVersion = value; }
|
||||
//}
|
||||
|
||||
public HttpMethod Method
|
||||
{
|
||||
get { return this.method; }
|
||||
set { this.method = value; }
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the headers of this message.
|
||||
*/
|
||||
public WebHeaderCollection Headers
|
||||
{
|
||||
get { return this.headers; }
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the body of this message.
|
||||
*/
|
||||
public object Body
|
||||
{
|
||||
get { return this.body; }
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@code HttpRequestMessage} with no body and no headers.
|
||||
*/
|
||||
public HttpRequestMessage(HttpMethod method) :
|
||||
this(null, new WebHeaderCollection(), method)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@code HttpRequestMessage} with the given headers and no body.
|
||||
* @param headers the message headers
|
||||
*/
|
||||
public HttpRequestMessage(WebHeaderCollection headers) :
|
||||
this(null, headers, HttpMethod.GET)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@code HttpRequestMessage} with the given headers and no body.
|
||||
* @param headers the message headers
|
||||
*/
|
||||
public HttpRequestMessage(WebHeaderCollection headers, HttpMethod method) :
|
||||
this(null, headers, method)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@code HttpRequestMessage} with the given body and no headers.
|
||||
* @param body the message body
|
||||
*/
|
||||
public HttpRequestMessage(object body) :
|
||||
this(body, new WebHeaderCollection(), HttpMethod.GET)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@code HttpRequestMessage} with the given body and no headers.
|
||||
* @param body the message body
|
||||
*/
|
||||
public HttpRequestMessage(object body, HttpMethod method) :
|
||||
this(body, new WebHeaderCollection(), method)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@code HttpRequestMessage} with the given body and headers.
|
||||
* @param body the messagae body
|
||||
* @param headers the message headers
|
||||
*/
|
||||
public HttpRequestMessage(object body, WebHeaderCollection headers) :
|
||||
this(body, headers, HttpMethod.GET)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@code HttpRequestMessage} with the given body and headers.
|
||||
* @param body the messagae body
|
||||
* @param headers the message headers
|
||||
*/
|
||||
public HttpRequestMessage(object body, WebHeaderCollection headers, HttpMethod method)
|
||||
{
|
||||
this.method = method;
|
||||
this.body = body;
|
||||
this.headers = headers;
|
||||
}
|
||||
}
|
||||
}
|
||||
107
src/Spring/Spring.Http/Http/HttpResponseMessage.cs
Normal file
107
src/Spring/Spring.Http/Http/HttpResponseMessage.cs
Normal file
@@ -0,0 +1,107 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System.Net;
|
||||
|
||||
namespace Spring.Http
|
||||
{
|
||||
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html#sec6
|
||||
public class HttpResponseMessage<T> where T : class
|
||||
{
|
||||
private WebHeaderCollection headers;
|
||||
private T body;
|
||||
private HttpStatusCode statusCode;
|
||||
private string statusDescription;
|
||||
|
||||
/**
|
||||
* Returns the headers of this entity.
|
||||
*/
|
||||
public WebHeaderCollection Headers
|
||||
{
|
||||
get { return this.headers; }
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the body of this entity.
|
||||
*/
|
||||
public T Body
|
||||
{
|
||||
get { return this.body; }
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the HTTP status code of the response.
|
||||
* @return the HTTP status as an HttpStatus enum value
|
||||
*/
|
||||
public HttpStatusCode StatusCode
|
||||
{
|
||||
get { return statusCode; }
|
||||
}
|
||||
|
||||
public string StatusDescription
|
||||
{
|
||||
get { return statusDescription; }
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@code ResponseEntity} with the given status code, and no body, no headers.
|
||||
* @param body the entity body
|
||||
* @param statusCode the status code
|
||||
*/
|
||||
public HttpResponseMessage(HttpStatusCode statusCode, string statusDescription) :
|
||||
this(null, null, statusCode, statusDescription)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@code ResponseEntity} with the given body and status code, and no headers.
|
||||
* @param body the entity body
|
||||
* @param statusCode the status code
|
||||
*/
|
||||
public HttpResponseMessage(T body, HttpStatusCode statusCode, string statusDescription) :
|
||||
this(body, null, statusCode, statusDescription)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@code HttpEntity} with the given headers and status code, and no body.
|
||||
* @param headers the entity headers
|
||||
* @param statusCode the status code
|
||||
*/
|
||||
public HttpResponseMessage(WebHeaderCollection headers, HttpStatusCode statusCode, string statusDescription) :
|
||||
this(null, headers, statusCode, statusDescription)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@code HttpEntity} with the given body, headers, and status code.
|
||||
* @param body the entity body
|
||||
* @param headers the entity headers
|
||||
* @param statusCode the status code
|
||||
*/
|
||||
public HttpResponseMessage(T body, WebHeaderCollection headers, HttpStatusCode statusCode, string statusDescription)
|
||||
{
|
||||
this.statusCode = statusCode;
|
||||
this.statusDescription = statusDescription;
|
||||
this.body = body;
|
||||
this.headers = headers;
|
||||
}
|
||||
}
|
||||
}
|
||||
46
src/Spring/Spring.Http/Http/IHttpWebRequestFactory.cs
Normal file
46
src/Spring/Spring.Http/Http/IHttpWebRequestFactory.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
|
||||
namespace Spring.Http
|
||||
{
|
||||
/**
|
||||
* Factory for {@link ClientHttpRequest} objects.
|
||||
* Requests are created by the {@link #createRequest(URI, HttpMethod)} method.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 3.0
|
||||
*/
|
||||
public interface IHttpWebRequestFactory
|
||||
{
|
||||
/**
|
||||
* Create a new {@link ClientHttpRequest} for the specified URI and HTTP method.
|
||||
* <p>The returned request can be written to, and then executed by calling
|
||||
* {@link ClientHttpRequest#execute()}.
|
||||
* @param uri the URI to create a request for
|
||||
* @param httpMethod the HTTP method to execute
|
||||
* @return the created request
|
||||
* @throws IOException in case of I/O errors
|
||||
*/
|
||||
HttpWebRequest CreateRequest(Uri uri);
|
||||
}
|
||||
}
|
||||
790
src/Spring/Spring.Http/Http/MediaType.cs
Normal file
790
src/Spring/Spring.Http/Http/MediaType.cs
Normal file
@@ -0,0 +1,790 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Globalization;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Spring.Util;
|
||||
|
||||
namespace Spring.Http
|
||||
{
|
||||
/**
|
||||
* Represents an Internet Media Type, as defined in the HTTP specification.
|
||||
*
|
||||
* <p>Consists of a {@linkplain #getType() type} and a {@linkplain #getSubtype() subtype}.
|
||||
* Also has functionality to parse media types from a string using {@link #parseMediaType(String)},
|
||||
* or multiple comma-separated media types using {@link #parseMediaTypes(String)}.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
* @see <a href="http://tools.ietf.org/html/rfc2616#section-3.7">HTTP 1.1, section 3.7</a>
|
||||
*/
|
||||
public class MediaType : IComparable<MediaType>
|
||||
{
|
||||
/**
|
||||
* Public constant media type that includes all media ranges (i.e. <code>*/*</code>).
|
||||
*/
|
||||
public static readonly MediaType ALL = new MediaType("*", "*");
|
||||
|
||||
/**
|
||||
* Public constant media type for {@code application/atom+xml}.
|
||||
*/
|
||||
public static readonly MediaType APPLICATION_ATOM_XML = new MediaType("application", "atom+xml");
|
||||
|
||||
/**
|
||||
* Public constant media type for {@code application/x-www-form-urlencoded}.
|
||||
* */
|
||||
public static readonly MediaType APPLICATION_FORM_URLENCODED = new MediaType("application", "x-www-form-urlencoded");
|
||||
|
||||
/**
|
||||
* Public constant media type for {@code application/json}.
|
||||
* */
|
||||
public static readonly MediaType APPLICATION_JSON = new MediaType("application", "json");
|
||||
|
||||
/**
|
||||
* Public constant media type for {@code application/octet-stream}.
|
||||
* */
|
||||
public static readonly MediaType APPLICATION_OCTET_STREAM = new MediaType("application", "octet-stream");
|
||||
|
||||
/**
|
||||
* Public constant media type for {@code application/xhtml+xml}.
|
||||
* */
|
||||
public static readonly MediaType APPLICATION_XHTML_XML = new MediaType("application", "xhtml+xml");
|
||||
|
||||
/**
|
||||
* Public constant media type for {@code image/gif}.
|
||||
*/
|
||||
public static readonly MediaType IMAGE_GIF = new MediaType("image", "gif");
|
||||
|
||||
/**
|
||||
* Public constant media type for {@code image/jpeg}.
|
||||
*/
|
||||
public static readonly MediaType IMAGE_JPEG = new MediaType("image", "jpeg");
|
||||
|
||||
/**
|
||||
* Public constant media type for {@code image/png}.
|
||||
*/
|
||||
public static readonly MediaType IMAGE_PNG = new MediaType("image", "png");
|
||||
|
||||
/**
|
||||
* Public constant media type for {@code image/xml}.
|
||||
*/
|
||||
public static readonly MediaType APPLICATION_XML = new MediaType("application", "xml");
|
||||
|
||||
/**
|
||||
* Public constant media type for {@code multipart/form-data}.
|
||||
* */
|
||||
public static readonly MediaType MULTIPART_FORM_DATA = new MediaType("multipart", "form-data");
|
||||
|
||||
/**
|
||||
* Public constant media type for {@code text/html}.
|
||||
* */
|
||||
public static readonly MediaType TEXT_HTML = new MediaType("text", "html");
|
||||
|
||||
/**
|
||||
* Public constant media type for {@code text/plain}.
|
||||
* */
|
||||
public static readonly MediaType TEXT_PLAIN = new MediaType("text", "plain");
|
||||
|
||||
/**
|
||||
* Public constant media type for {@code text/xml}.
|
||||
* */
|
||||
public static readonly MediaType TEXT_XML = new MediaType("text", "xml");
|
||||
|
||||
|
||||
private const string WILDCARD_TYPE = "*";
|
||||
|
||||
private const string PARAM_QUALITY_FACTOR = "q";
|
||||
|
||||
private const string PARAM_CHARSET = "charset";
|
||||
|
||||
private string type;
|
||||
|
||||
private string subtype;
|
||||
|
||||
private IDictionary<string, string> parameters;
|
||||
|
||||
/**
|
||||
* Return the primary type.
|
||||
*/
|
||||
public string Type
|
||||
{
|
||||
get { return this.type; }
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the subtype.
|
||||
*/
|
||||
public string Subtype
|
||||
{
|
||||
get { return this.subtype; }
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate whether the {@linkplain #getType() type} is the wildcard character <code>*</code> or not.
|
||||
*/
|
||||
public bool IsWildcardType
|
||||
{
|
||||
get { return WILDCARD_TYPE == type; }
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate whether the {@linkplain #getSubtype() subtype} is the wildcard character <code>*</code> or not.
|
||||
* @return whether the subtype is <code>*</code>
|
||||
*/
|
||||
public bool IsWildcardSubtype
|
||||
{
|
||||
get { return WILDCARD_TYPE == subtype; }
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the character set, as indicated by a <code>charset</code> parameter, if any.
|
||||
* @return the character set; or <code>null</code> if not available
|
||||
*/
|
||||
public string CharSet
|
||||
{
|
||||
get
|
||||
{
|
||||
string charSet = null;
|
||||
this.parameters.TryGetValue(PARAM_CHARSET, out charSet);
|
||||
return charSet;
|
||||
//string charSet = this.parameters[PARAM_CHARSET];
|
||||
//return (charSet != null ? Charset.forName(charSet) : null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the quality value, as indicated by a <code>q</code> parameter, if any.
|
||||
* Defaults to <code>1.0</code>.
|
||||
* @return the quality factory
|
||||
*/
|
||||
public double QualityValue
|
||||
{
|
||||
get
|
||||
{
|
||||
string qualityFactory = null;
|
||||
return this.parameters.TryGetValue(PARAM_QUALITY_FACTOR, out qualityFactory)
|
||||
? Double.Parse(qualityFactory, CultureInfo.InvariantCulture)
|
||||
: 1D;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link MediaType} for the given primary type.
|
||||
* <p>The {@linkplain #getSubtype() subtype} is set to <code>*</code>, parameters empty.
|
||||
* @param type the primary type
|
||||
* @throws IllegalArgumentException if any of the parameters contain illegal characters
|
||||
*/
|
||||
public MediaType(string type) :
|
||||
this(type, WILDCARD_TYPE)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link MediaType} for the given primary type and subtype.
|
||||
* <p>The parameters are empty.
|
||||
* @param type the primary type
|
||||
* @param subtype the subtype
|
||||
* @throws IllegalArgumentException if any of the parameters contain illegal characters
|
||||
*/
|
||||
public MediaType(string type, string subtype) :
|
||||
this(type, subtype, new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase))
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link MediaType} for the given type, subtype, and character set.
|
||||
* @param type the primary type
|
||||
* @param subtype the subtype
|
||||
* @param charSet the character set
|
||||
* @throws IllegalArgumentException if any of the parameters contain illegal characters
|
||||
*/
|
||||
public MediaType(string type, string subtype, string charSet) :
|
||||
this(type, subtype)
|
||||
{
|
||||
this.parameters.Add(PARAM_CHARSET, charSet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link MediaType} for the given type, subtype, and quality value.
|
||||
*
|
||||
* @param type the primary type
|
||||
* @param subtype the subtype
|
||||
* @param qualityValue the quality value
|
||||
* @throws IllegalArgumentException if any of the parameters contain illegal characters
|
||||
*/
|
||||
public MediaType(String type, String subtype, double qualityValue) :
|
||||
this(type, subtype)
|
||||
{
|
||||
this.parameters.Add(PARAM_QUALITY_FACTOR, qualityValue.ToString(CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy-constructor that copies the type and subtype of the given {@link MediaType},
|
||||
* and allows for different parameter.
|
||||
* @param other the other media type
|
||||
* @param parameters the parameters, may be <code>null</code>
|
||||
* @throws IllegalArgumentException if any of the parameters contain illegal characters
|
||||
*/
|
||||
public MediaType(MediaType other, IDictionary<string, string> parameters) :
|
||||
this(other.Type, other.Subtype, parameters)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link MediaType} for the given type, subtype, and parameters.
|
||||
* @param type the primary type
|
||||
* @param subtype the subtype
|
||||
* @param parameters the parameters, may be <code>null</code>
|
||||
* @throws IllegalArgumentException if any of the parameters contain illegal characters
|
||||
*/
|
||||
public MediaType(string type, string subtype, IDictionary<string, string> parameters)
|
||||
{
|
||||
AssertUtils.ArgumentHasText(type, "'type' must not be empty");
|
||||
AssertUtils.ArgumentHasText(subtype, "'subtype' must not be empty");
|
||||
//checkToken(type);
|
||||
//checkToken(subtype);
|
||||
this.type = type.ToLowerInvariant();
|
||||
this.subtype = subtype.ToLowerInvariant();
|
||||
this.parameters = new Dictionary<string, string>(parameters, StringComparer.InvariantCultureIgnoreCase);
|
||||
//if (parameters.Count > 0)
|
||||
//{
|
||||
// NameValueCollection m = new NameValueCollection(parameters.Count, null, new CaseInsensitiveComparer());
|
||||
// for (Map.Entry<String, String> entry : parameters.entrySet()) {
|
||||
// String attribute = entry.getKey();
|
||||
// String value = entry.getValue();
|
||||
// checkParameters(attribute, value);
|
||||
// m.put(attribute, unquote(value));
|
||||
// }
|
||||
// this.parameters = Collections.unmodifiableMap(m);
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// this.parameters = Collections.emptyMap();
|
||||
//}
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (this == obj)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (obj is MediaType)
|
||||
{
|
||||
MediaType otherMediaType = (MediaType)obj;
|
||||
if (this.type == otherMediaType.type &&
|
||||
this.subtype == otherMediaType.subtype)
|
||||
{
|
||||
if (otherMediaType.parameters.Count == this.parameters.Count)
|
||||
{
|
||||
foreach(string key in this.parameters.Keys)
|
||||
{
|
||||
if (!otherMediaType.parameters.ContainsKey(key) ||
|
||||
!String.Equals(otherMediaType.parameters[key], this.parameters[key]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
int result = this.type.GetHashCode();
|
||||
result = 31 * result + this.subtype.GetHashCode();
|
||||
result = 31 * result + this.parameters.GetHashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.Append(this.type);
|
||||
builder.Append('/');
|
||||
builder.Append(this.subtype);
|
||||
foreach(string key in this.parameters.Keys)
|
||||
{
|
||||
builder.Append(';');
|
||||
builder.Append(key);
|
||||
builder.Append('=');
|
||||
builder.Append(this.parameters[key]);
|
||||
}
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the given token string for illegal characters, as defined in RFC 2616, section 2.2.
|
||||
* @throws IllegalArgumentException in case of illegal characters
|
||||
* @see <a href="http://tools.ietf.org/html/rfc2616#section-2.2">HTTP 1.1, section 2.2</a>
|
||||
*/
|
||||
//private void checkToken(String s) {
|
||||
// for (int i=0; i < s.length(); i++ ) {
|
||||
// char ch = s.charAt(i);
|
||||
// if (!TOKEN.get(ch)) {
|
||||
// throw new IllegalArgumentException("Invalid token character '" + ch + "' in token \"" + s + "\"");
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
//private void checkParameters(String attribute, String value) {
|
||||
// Assert.hasLength(attribute, "parameter attribute must not be empty");
|
||||
// Assert.hasLength(value, "parameter value must not be empty");
|
||||
// checkToken(attribute);
|
||||
// if (PARAM_QUALITY_FACTOR.equals(attribute)) {
|
||||
// value = unquote(value);
|
||||
// double d = Double.parseDouble(value);
|
||||
// Assert.isTrue(d >= 0D && d <= 1D,
|
||||
// "Invalid quality value \"" + value + "\": should be between 0.0 and 1.0");
|
||||
// }
|
||||
// else if (PARAM_CHARSET.equals(attribute)) {
|
||||
// value = unquote(value);
|
||||
// Charset.forName(value);
|
||||
// }
|
||||
// else if (!isQuotedString(value)) {
|
||||
// checkToken(value);
|
||||
// }
|
||||
//}
|
||||
|
||||
//private boolean isQuotedString(String s) {
|
||||
// return s.length() > 1 && s.startsWith("\"") && s.endsWith("\"") ;
|
||||
//}
|
||||
|
||||
//private String unquote(String s) {
|
||||
// if (s == null) {
|
||||
// return null;
|
||||
// }
|
||||
// return isQuotedString(s) ? s.substring(1, s.length() - 1) : s;
|
||||
//}
|
||||
|
||||
/**
|
||||
* Return a generic parameter value, given a parameter name.
|
||||
* @param name the parameter name
|
||||
* @return the parameter value; or <code>null</code> if not present
|
||||
*/
|
||||
public string GetParameter(string name)
|
||||
{
|
||||
return this.parameters[name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate whether this {@link MediaType} includes the given media type.
|
||||
* <p>For instance, {@code text/*} includes {@code text/plain}, {@code text/html}, and {@code application/*+xml}
|
||||
* includes {@code application/soap+xml}, etc. This method is non-symmetic.
|
||||
* @param other the reference media type with which to compare
|
||||
* @return <code>true</code> if this media type includes the given media type; <code>false</code> otherwise
|
||||
*/
|
||||
public bool Includes(MediaType other)
|
||||
{
|
||||
if (other == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (this.IsWildcardType)
|
||||
{
|
||||
// */* includes anything
|
||||
return true;
|
||||
}
|
||||
else if (this.type == other.type)
|
||||
{
|
||||
if (this.subtype == other.subtype || this.IsWildcardSubtype)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// application/*+xml includes application/soap+xml
|
||||
int thisPlusIdx = this.subtype.IndexOf('+');
|
||||
int otherPlusIdx = other.subtype.IndexOf('+');
|
||||
if (thisPlusIdx != -1 && otherPlusIdx != -1)
|
||||
{
|
||||
string thisSubtypeNoSuffix = this.subtype.Substring(0, thisPlusIdx);
|
||||
|
||||
string thisSubtypeSuffix = this.subtype.Substring(thisPlusIdx + 1);
|
||||
string otherSubtypeSuffix = other.subtype.Substring(otherPlusIdx + 1);
|
||||
if (thisSubtypeSuffix == otherSubtypeSuffix && WILDCARD_TYPE == thisSubtypeNoSuffix)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate whether this {@link MediaType} is compatible with the given media type.
|
||||
* <p>For instance, {@code text/*} is compatible with {@code text/plain}, {@code text/html}, and vice versa.
|
||||
* In effect, this method is similar to {@link #includes(MediaType)}, except that it's symmetric.
|
||||
* @param other the reference media type with which to compare
|
||||
* @return <code>true</code> if this media type is compatible with the given media type; <code>false</code> otherwise
|
||||
*/
|
||||
public bool IsCompatibleWith(MediaType other)
|
||||
{
|
||||
if (other == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (this.IsWildcardType || other.IsWildcardType)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (this.type == other.type)
|
||||
{
|
||||
if (this.subtype == other.subtype || this.IsWildcardSubtype || other.IsWildcardSubtype)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// application/*+xml is compatible with application/soap+xml, and vice-versa
|
||||
int thisPlusIdx = this.subtype.IndexOf('+');
|
||||
int otherPlusIdx = other.subtype.IndexOf('+');
|
||||
if (thisPlusIdx != -1 && otherPlusIdx != -1)
|
||||
{
|
||||
string thisSubtypeNoSuffix = this.subtype.Substring(0, thisPlusIdx);
|
||||
string otherSubtypeNoSuffix = other.subtype.Substring(0, otherPlusIdx);
|
||||
|
||||
string thisSubtypeSuffix = this.subtype.Substring(thisPlusIdx + 1);
|
||||
string otherSubtypeSuffix = other.subtype.Substring(otherPlusIdx + 1);
|
||||
|
||||
if (thisSubtypeSuffix == otherSubtypeSuffix &&
|
||||
(WILDCARD_TYPE == thisSubtypeNoSuffix || WILDCARD_TYPE == otherSubtypeNoSuffix))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#region IComparable<MediaType> Membres
|
||||
|
||||
/**
|
||||
* Compares this {@link MediaType} to another alphabetically.
|
||||
* @param other media type to compare to
|
||||
* @see #sortBySpecificity(List)
|
||||
*/
|
||||
public int CompareTo(MediaType other)
|
||||
{
|
||||
int comp = this.type.CompareTo(other.type);
|
||||
if (comp != 0)
|
||||
{
|
||||
return comp;
|
||||
}
|
||||
comp = this.subtype.CompareTo(other.subtype);
|
||||
if (comp != 0)
|
||||
{
|
||||
return comp;
|
||||
}
|
||||
comp = this.parameters.Count - other.parameters.Count;
|
||||
if (comp != 0)
|
||||
{
|
||||
return comp;
|
||||
}
|
||||
foreach(string key in this.parameters.Keys)
|
||||
{
|
||||
if (!other.parameters.ContainsKey(key))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
comp = String.Compare(this.parameters[key], other.parameters[key]);
|
||||
if (comp != 0)
|
||||
{
|
||||
return comp;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/**
|
||||
* Parse the given String into a single {@link MediaType}.
|
||||
* @param mediaType the string to parse
|
||||
* @return the media type
|
||||
* @throws IllegalArgumentException if the string cannot be parsed
|
||||
*/
|
||||
public static MediaType ParseMediaType(string mediaType)
|
||||
{
|
||||
AssertUtils.ArgumentHasText(mediaType, "'mediaType' must not be empty");
|
||||
|
||||
string[] parts = mediaType.Split(';');
|
||||
string fullType = parts[0].Trim();
|
||||
if (fullType == WILDCARD_TYPE)
|
||||
{
|
||||
fullType = "*/*";
|
||||
}
|
||||
int subIndex = fullType.IndexOf('/');
|
||||
if (subIndex == -1)
|
||||
{
|
||||
throw new ArgumentException(
|
||||
String.Format("'{0}' does not contain '/'", mediaType),
|
||||
"mediaType");
|
||||
}
|
||||
if (subIndex == fullType.Length - 1)
|
||||
{
|
||||
throw new ArgumentException(
|
||||
String.Format("'{0}' does not contain subtype after '/'", mediaType),
|
||||
"mediaType");
|
||||
}
|
||||
string type = fullType.Substring(0, subIndex);
|
||||
string subtype = fullType.Substring(subIndex + 1);
|
||||
|
||||
IDictionary<string, string> parameters = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase);
|
||||
if (parts.Length > 1)
|
||||
{
|
||||
for (int i = 1; i < parts.Length; i++)
|
||||
{
|
||||
string parameter = parts[i].Trim();
|
||||
int eqIndex = parameter.IndexOf('=');
|
||||
if (eqIndex != -1)
|
||||
{
|
||||
string attribute = parameter.Substring(0, eqIndex);
|
||||
string value = parameter.Substring(eqIndex + 1);
|
||||
parameters.Add(attribute, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new MediaType(type, subtype, parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the given, comma-seperated string into a list of {@link MediaType} objects.
|
||||
* <p>This method can be used to parse an Accept or Content-Type header.
|
||||
* @param mediaTypes the string to parse
|
||||
* @return the list of media types
|
||||
* @throws IllegalArgumentException if the string cannot be parsed
|
||||
*/
|
||||
public static List<MediaType> ParseMediaTypes(string mediaTypes)
|
||||
{
|
||||
List<MediaType> mediaTypeList = new List<MediaType>();
|
||||
if (!StringUtils.HasLength(mediaTypes))
|
||||
{
|
||||
return mediaTypeList;
|
||||
}
|
||||
string[] tokens = mediaTypes.Split(',');
|
||||
foreach (string token in tokens)
|
||||
{
|
||||
mediaTypeList.Add(ParseMediaType(token));
|
||||
}
|
||||
return mediaTypeList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a string representation of the given list of {@link MediaType} objects.
|
||||
* <p>This method can be used to for an {@code Accept} or {@code Content-Type} header.
|
||||
* @param mediaTypes the string to parse
|
||||
* @return the list of media types
|
||||
* @throws IllegalArgumentException if the String cannot be parsed
|
||||
*/
|
||||
public static string ToString(IEnumerable<MediaType> mediaTypes)
|
||||
{
|
||||
StringBuilder builder = new StringBuilder();
|
||||
foreach(MediaType mediaType in mediaTypes)
|
||||
{
|
||||
if (builder.Length > 0)
|
||||
{
|
||||
builder.Append(", ");
|
||||
}
|
||||
builder.Append(mediaType);
|
||||
}
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the given list of {@link MediaType} objects by specificity.
|
||||
* <p>Given two media types:
|
||||
* <ol>
|
||||
* <li>if either media type has a {@linkplain #isWildcardType() wildcard type}, then the media type without the
|
||||
* wildcard is ordered before the other.</li>
|
||||
* <li>if the two media types have different {@linkplain #getType() types}, then they are considered equal and
|
||||
* remain their current order.</li>
|
||||
* <li>if either media type has a {@linkplain #isWildcardSubtype() wildcard subtype}, then the media type without
|
||||
* the wildcard is sorted before the other.</li>
|
||||
* <li>if the two media types have different {@linkplain #getSubtype() subtypes}, then they are considered equal
|
||||
* and remain their current order.</li>
|
||||
* <li>if the two media types have different {@linkplain #getQualityValue() quality value}, then the media type
|
||||
* with the highest quality value is ordered before the other.</li>
|
||||
* <li>if the two media types have a different amount of {@linkplain #getParameter(String) parameters}, then the
|
||||
* media type with the most parameters is ordered before the other.</li>
|
||||
* </ol>
|
||||
* <p>For example:
|
||||
* <blockquote>audio/basic < audio/* < */*</blockquote>
|
||||
* <blockquote>audio/* < audio/*;q=0.7; audio/*;q=0.3</blockquote>
|
||||
* <blockquote>audio/basic;level=1 < audio/basic</blockquote>
|
||||
* <blockquote>audio/basic == text/html</blockquote>
|
||||
* <blockquote>audio/basic == audio/wave</blockquote>
|
||||
* @param mediaTypes the list of media types to be sorted
|
||||
* @see <a href="http://tools.ietf.org/html/rfc2616#section-14.1">HTTP 1.1, section 14.1</a>
|
||||
*/
|
||||
public static void SortBySpecificity(List<MediaType> mediaTypes)
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(mediaTypes, "mediaTypes");
|
||||
|
||||
if (mediaTypes.Count > 1)
|
||||
{
|
||||
mediaTypes.Sort(SPECIFICITY_COMPARER);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the given list of {@link MediaType} objects by quality value.
|
||||
* <p>Given two media types:
|
||||
* <ol>
|
||||
* <li>if the two media types have different {@linkplain #getQualityValue() quality value}, then the media type
|
||||
* with the highest quality value is ordered before the other.</li>
|
||||
* <li>if either media type has a {@linkplain #isWildcardType() wildcard type}, then the media type without the
|
||||
* wildcard is ordered before the other.</li>
|
||||
* <li>if the two media types have different {@linkplain #getType() types}, then they are considered equal and
|
||||
* remain their current order.</li>
|
||||
* <li>if either media type has a {@linkplain #isWildcardSubtype() wildcard subtype}, then the media type without
|
||||
* the wildcard is sorted before the other.</li>
|
||||
* <li>if the two media types have different {@linkplain #getSubtype() subtypes}, then they are considered equal
|
||||
* and remain their current order.</li>
|
||||
* <li>if the two media types have a different amount of {@linkplain #getParameter(String) parameters}, then the
|
||||
* media type with the most parameters is ordered before the other.</li>
|
||||
* </ol>
|
||||
* @param mediaTypes the list of media types to be sorted
|
||||
* @see #getQualityValue()
|
||||
*/
|
||||
public static void SortByQualityValue(List<MediaType> mediaTypes)
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(mediaTypes, "mediaTypes");
|
||||
|
||||
if (mediaTypes.Count > 1)
|
||||
{
|
||||
mediaTypes.Sort(QUALITY_VALUE_COMPARER);
|
||||
}
|
||||
}
|
||||
|
||||
public static IComparer<MediaType> SPECIFICITY_COMPARER = new SpecificityComparer();
|
||||
public static IComparer<MediaType> QUALITY_VALUE_COMPARER = new QualityValueComparer();
|
||||
|
||||
#region SpecificityComparer
|
||||
|
||||
private class SpecificityComparer : IComparer<MediaType>
|
||||
{
|
||||
public int Compare(MediaType x, MediaType y)
|
||||
{
|
||||
if (x.IsWildcardType && !y.IsWildcardType)
|
||||
{ // */* < audio/*
|
||||
return 1;
|
||||
}
|
||||
else if (y.IsWildcardType && !x.IsWildcardType)
|
||||
{ // audio/* > */*
|
||||
return -1;
|
||||
}
|
||||
else if (x.type != y.type)
|
||||
{ // audio/basic == text/html
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{ // mediaType1.type == mediaType2.type
|
||||
if (x.IsWildcardSubtype && !y.IsWildcardSubtype)
|
||||
{ // audio/* < audio/basic
|
||||
return 1;
|
||||
}
|
||||
else if (y.IsWildcardSubtype && !x.IsWildcardSubtype)
|
||||
{ // audio/basic > audio/*
|
||||
return -1;
|
||||
}
|
||||
else if (x.subtype != y.subtype)
|
||||
{ // audio/basic == audio/wave
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{ // mediaType2.subtype == mediaType2.subtype
|
||||
double quality1 = x.QualityValue;
|
||||
double quality2 = y.QualityValue;
|
||||
int qualityComparison = quality2.CompareTo(quality1);
|
||||
if (qualityComparison != 0)
|
||||
{
|
||||
return qualityComparison; // audio/*;q=0.7 < audio/*;q=0.3
|
||||
}
|
||||
else
|
||||
{
|
||||
int paramsSize1 = x.parameters.Count;
|
||||
int paramsSize2 = y.parameters.Count;
|
||||
return (paramsSize2 < paramsSize1 ? -1 : (paramsSize2 == paramsSize1 ? 0 : 1)); // audio/basic;level=1 < audio/basic
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region QualityValueComparer
|
||||
|
||||
private class QualityValueComparer : IComparer<MediaType>
|
||||
{
|
||||
public int Compare(MediaType x, MediaType y)
|
||||
{
|
||||
double quality1 = x.QualityValue;
|
||||
double quality2 = y.QualityValue;
|
||||
int qualityComparison = quality2.CompareTo(quality1);
|
||||
if (qualityComparison != 0)
|
||||
{
|
||||
return qualityComparison; // audio/*;q=0.7 < audio/*;q=0.3
|
||||
}
|
||||
else if (x.IsWildcardType && !y.IsWildcardType)
|
||||
{ // */* < audio/*
|
||||
return 1;
|
||||
}
|
||||
else if (y.IsWildcardType && !x.IsWildcardType)
|
||||
{ // audio/* > */*
|
||||
return -1;
|
||||
}
|
||||
else if (x.type != y.type)
|
||||
{ // audio/basic == text/html
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{ // mediaType1.type == mediaType2.type
|
||||
if (x.IsWildcardSubtype && !y.IsWildcardSubtype)
|
||||
{ // audio/* < audio/basic
|
||||
return 1;
|
||||
}
|
||||
else if (y.IsWildcardSubtype && !x.IsWildcardSubtype)
|
||||
{ // audio/basic > audio/*
|
||||
return -1;
|
||||
}
|
||||
else if (x.subtype != y.subtype)
|
||||
{ // audio/basic == audio/wave
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
int paramsSize1 = x.parameters.Count;
|
||||
int paramsSize2 = y.parameters.Count;
|
||||
return (paramsSize2 < paramsSize1 ? -1 : (paramsSize2 == paramsSize1 ? 0 : 1)); // audio/basic;level=1 < audio/basic
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
47
src/Spring/Spring.Http/Http/Rest/IRequestCallback.cs
Normal file
47
src/Spring/Spring.Http/Http/Rest/IRequestCallback.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
|
||||
namespace Spring.Http.Rest
|
||||
{
|
||||
/**
|
||||
* Callback interface for code that operates on a {@link ClientHttpRequest}. Allows to manipulate the request
|
||||
* headers, and write to the request body.
|
||||
*
|
||||
* <p>Used internally by the {@link RestTemplate}, but also useful for application code.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @see RestTemplate#execute
|
||||
* @since 3.0
|
||||
*/
|
||||
public interface IRequestCallback
|
||||
{
|
||||
/**
|
||||
* Gets called by {@link RestTemplate#execute} with an opened {@code ClientHttpRequest}.
|
||||
* Does not need to care about closing the request or about handling errors:
|
||||
* this will all be handled by the {@code RestTemplate}.
|
||||
* @param request the active HTTP request
|
||||
* @throws IOException in case of I/O errors
|
||||
*/
|
||||
void DoWithRequest(HttpWebRequest request);
|
||||
}
|
||||
}
|
||||
48
src/Spring/Spring.Http/Http/Rest/IResponseExtractor.cs
Normal file
48
src/Spring/Spring.Http/Http/Rest/IResponseExtractor.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
|
||||
namespace Spring.Http.Rest
|
||||
{
|
||||
/**
|
||||
* Generic callback interface used by {@link RestTemplate}'s retrieval methods
|
||||
* Implementations of this interface perform the actual work of extracting data
|
||||
* from a {@link ClientHttpResponse}, but don't need to worry about exception
|
||||
* handling or closing resources.
|
||||
*
|
||||
* <p>Used internally by the {@link RestTemplate}, but also useful for application code.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 3.0
|
||||
* @see RestTemplate#execute
|
||||
*/
|
||||
public interface IResponseExtractor<T> where T : class
|
||||
{
|
||||
/**
|
||||
* Extract data from the given {@code ClientHttpResponse} and return it.
|
||||
* @param response the HTTP response
|
||||
* @return the extracted data
|
||||
* @throws IOException in case of I/O errors
|
||||
*/
|
||||
T ExtractData(HttpWebResponse response); // throws IOException;
|
||||
}
|
||||
}
|
||||
439
src/Spring/Spring.Http/Http/Rest/IRestOperations.cs
Normal file
439
src/Spring/Spring.Http/Http/Rest/IRestOperations.cs
Normal file
@@ -0,0 +1,439 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Spring.Http;
|
||||
|
||||
namespace Spring.Http.Rest
|
||||
{
|
||||
public interface IRestOperations
|
||||
{
|
||||
#region GET
|
||||
|
||||
/**
|
||||
* Retrieve a representation by doing a GET on the specified URL.
|
||||
* The response (if any) is converted and returned.
|
||||
* <p>URI Template variables are expanded using the given URI variables, if any.
|
||||
* @param url the URL
|
||||
* @param responseType the type of the return value
|
||||
* @param uriVariables the variables to expand the template
|
||||
* @return the converted object
|
||||
*/
|
||||
T GetForObject<T>(string url, params string[] uriVariables) where T : class; //throws RestClientException;
|
||||
|
||||
/**
|
||||
* Retrieve a representation by doing a GET on the URI template.
|
||||
* The response (if any) is converted and returned.
|
||||
* <p>URI Template variables are expanded using the given map.
|
||||
* @param url the URL
|
||||
* @param responseType the type of the return value
|
||||
* @param uriVariables the map containing variables for the URI template
|
||||
* @return the converted object
|
||||
*/
|
||||
T GetForObject<T>(string url, IDictionary<string, string> uriVariables) where T : class; //throws RestClientException;
|
||||
|
||||
/**
|
||||
* Retrieve a representation by doing a GET on the URL .
|
||||
* The response (if any) is converted and returned.
|
||||
* @param url the URL
|
||||
* @param responseType the type of the return value
|
||||
* @return the converted object
|
||||
*/
|
||||
T GetForObject<T>(Uri url) where T : class; //throws RestClientException;
|
||||
|
||||
/**
|
||||
* Retrieve an entity by doing a GET on the specified URL.
|
||||
* The response is converted and stored in an {@link ResponseEntity}.
|
||||
* <p>URI Template variables are expanded using the given URI variables, if any.
|
||||
* @param url the URL
|
||||
* @param responseType the type of the return value
|
||||
* @param uriVariables the variables to expand the template
|
||||
* @return the entity
|
||||
* @since 3.0.2
|
||||
*/
|
||||
HttpResponseMessage<T> GetForMessage<T>(string url, params string[] uriVariables) where T : class; //throws RestClientException;
|
||||
|
||||
/**
|
||||
* Retrieve a representation by doing a GET on the URI template.
|
||||
* The response is converted and stored in an {@link ResponseEntity}.
|
||||
* <p>URI Template variables are expanded using the given map.
|
||||
* @param url the URL
|
||||
* @param responseType the type of the return value
|
||||
* @param uriVariables the map containing variables for the URI template
|
||||
* @return the converted object
|
||||
* @since 3.0.2
|
||||
*/
|
||||
HttpResponseMessage<T> GetForMessage<T>(string url, IDictionary<string, string> uriVariables) where T : class; //throws RestClientException;
|
||||
|
||||
/**
|
||||
* Retrieve a representation by doing a GET on the URL .
|
||||
* The response is converted and stored in an {@link ResponseEntity}.
|
||||
* @param url the URL
|
||||
* @param responseType the type of the return value
|
||||
* @return the converted object
|
||||
* @since 3.0.2
|
||||
*/
|
||||
HttpResponseMessage<T> GetForMessage<T>(Uri url) where T : class; //throws RestClientException;
|
||||
|
||||
#endregion
|
||||
|
||||
#region HEAD
|
||||
|
||||
/**
|
||||
* Retrieve all headers of the resource specified by the URI template.
|
||||
* <p>URI Template variables are expanded using the given URI variables, if any.
|
||||
* @param url the URL
|
||||
* @param uriVariables the variables to expand the template
|
||||
* @return all HTTP headers of that resource
|
||||
*/
|
||||
WebHeaderCollection HeadForHeaders(string url, params string[] uriVariables); //throws RestClientException;
|
||||
|
||||
/**
|
||||
* Retrieve all headers of the resource specified by the URI template.
|
||||
* <p>URI Template variables are expanded using the given map.
|
||||
* @param url the URL
|
||||
* @param uriVariables the map containing variables for the URI template
|
||||
* @return all HTTP headers of that resource
|
||||
*/
|
||||
WebHeaderCollection HeadForHeaders(string url, IDictionary<string, string> uriVariables); //throws RestClientException;
|
||||
|
||||
/**
|
||||
* Retrieve all headers of the resource specified by the URL.
|
||||
* @param url the URL
|
||||
* @return all HTTP headers of that resource
|
||||
*/
|
||||
WebHeaderCollection HeadForHeaders(Uri url); //throws RestClientException;
|
||||
|
||||
#endregion
|
||||
|
||||
#region POST
|
||||
|
||||
/**
|
||||
* Create a new resource by POSTing the given object to the URI template, and returns the value of the
|
||||
* <code>Location</code> header. This header typically indicates where the new resource is stored.
|
||||
* <p>URI Template variables are expanded using the given URI variables, if any.
|
||||
* <p>The {@code request} parameter can be a {@link HttpEntity} in order to
|
||||
* add additional HTTP headers to the request.
|
||||
* @param url the URL
|
||||
* @param request the Object to be POSTed, may be <code>null</code>
|
||||
* @param uriVariables the variables to expand the template
|
||||
* @return the value for the <code>Location</code> header
|
||||
* @see HttpEntity
|
||||
*/
|
||||
Uri PostForLocation(string url, object request, params string[] uriVariables); //throws RestClientException;
|
||||
|
||||
/**
|
||||
* Create a new resource by POSTing the given object to the URI template, and returns the value of the
|
||||
* <code>Location</code> header. This header typically indicates where the new resource is stored.
|
||||
* <p>URI Template variables are expanded using the given map.
|
||||
* <p>The {@code request} parameter can be a {@link HttpEntity} in order to
|
||||
* add additional HTTP headers to the request.
|
||||
* @param url the URL
|
||||
* @param request the Object to be POSTed, may be <code>null</code>
|
||||
* @param uriVariables the variables to expand the template
|
||||
* @return the value for the <code>Location</code> header
|
||||
* @see HttpEntity
|
||||
*/
|
||||
Uri PostForLocation(string url, object request, IDictionary<string, string> uriVariables); //throws RestClientException;
|
||||
|
||||
/**
|
||||
* Create a new resource by POSTing the given object to the URL, and returns the value of the
|
||||
* <code>Location</code> header. This header typically indicates where the new resource is stored.
|
||||
* <p>The {@code request} parameter can be a {@link HttpEntity} in order to
|
||||
* add additional HTTP headers to the request.
|
||||
* @param url the URL
|
||||
* @param request the Object to be POSTed, may be <code>null</code>
|
||||
* @return the value for the <code>Location</code> header
|
||||
* @see HttpEntity
|
||||
*/
|
||||
Uri PostForLocation(Uri url, object request); //throws RestClientException;
|
||||
|
||||
/**
|
||||
* Create a new resource by POSTing the given object to the URI template,
|
||||
* and returns the representation found in the response.
|
||||
* <p>URI Template variables are expanded using the given URI variables, if any.
|
||||
* <p>The {@code request} parameter can be a {@link HttpEntity} in order to
|
||||
* add additional HTTP headers to the request.
|
||||
* @param url the URL
|
||||
* @param request the Object to be POSTed, may be <code>null</code>
|
||||
* @param responseType the type of the return value
|
||||
* @param uriVariables the variables to expand the template
|
||||
* @return the converted object
|
||||
* @see HttpEntity
|
||||
*/
|
||||
T PostForObject<T>(string url, object request, params string[] uriVariables) where T : class; //throws RestClientException;
|
||||
|
||||
/**
|
||||
* Create a new resource by POSTing the given object to the URI template,
|
||||
* and returns the representation found in the response.
|
||||
* <p>URI Template variables are expanded using the given map.
|
||||
* <p>The {@code request} parameter can be a {@link HttpEntity} in order to
|
||||
* add additional HTTP headers to the request.
|
||||
* @param url the URL
|
||||
* @param request the Object to be POSTed, may be <code>null</code>
|
||||
* @param responseType the type of the return value
|
||||
* @param uriVariables the variables to expand the template
|
||||
* @return the converted object
|
||||
* @see HttpEntity
|
||||
*/
|
||||
T PostForObject<T>(string url, object request, IDictionary<string, string> uriVariables) where T : class; //throws RestClientException;
|
||||
|
||||
/**
|
||||
* Create a new resource by POSTing the given object to the URL,
|
||||
* and returns the representation found in the response.
|
||||
* <p>The {@code request} parameter can be a {@link HttpEntity} in order to
|
||||
* add additional HTTP headers to the request.
|
||||
* @param url the URL
|
||||
* @param request the Object to be POSTed, may be <code>null</code>
|
||||
* @param responseType the type of the return value
|
||||
* @return the converted object
|
||||
* @see HttpEntity
|
||||
*/
|
||||
T PostForObject<T>(Uri url, object request) where T : class; //throws RestClientException;
|
||||
|
||||
/**
|
||||
* Create a new resource by POSTing the given object to the URI template,
|
||||
* and returns the response as {@link ResponseEntity}.
|
||||
* <p>URI Template variables are expanded using the given URI variables, if any.
|
||||
* <p>The {@code request} parameter can be a {@link HttpEntity} in order to
|
||||
* add additional HTTP headers to the request.
|
||||
* @param url the URL
|
||||
* @param request the Object to be POSTed, may be <code>null</code>
|
||||
* @param uriVariables the variables to expand the template
|
||||
* @return the converted object
|
||||
* @see HttpEntity
|
||||
* @since 3.0.2
|
||||
*/
|
||||
HttpResponseMessage<T> PostForMessage<T>(string url, object request, params string[] uriVariables) where T : class; //throws RestClientException;
|
||||
|
||||
/**
|
||||
* Create a new resource by POSTing the given object to the URI template,
|
||||
* and returns the response as {@link HttpEntity}.
|
||||
* <p>URI Template variables are expanded using the given map.
|
||||
* <p>The {@code request} parameter can be a {@link HttpEntity} in order to
|
||||
* add additional HTTP headers to the request.
|
||||
* @param url the URL
|
||||
* @param request the Object to be POSTed, may be <code>null</code>
|
||||
* @param uriVariables the variables to expand the template
|
||||
* @return the converted object
|
||||
* @see HttpEntity
|
||||
* @since 3.0.2
|
||||
*/
|
||||
HttpResponseMessage<T> PostForMessage<T>(string url, object request, IDictionary<string, string> uriVariables) where T : class; //throws RestClientException;
|
||||
|
||||
/**
|
||||
* Create a new resource by POSTing the given object to the URL,
|
||||
* and returns the response as {@link ResponseEntity}.
|
||||
* <p>The {@code request} parameter can be a {@link HttpEntity} in order to
|
||||
* add additional HTTP headers to the request.
|
||||
* @param url the URL
|
||||
* @param request the Object to be POSTed, may be <code>null</code>
|
||||
* @return the converted object
|
||||
* @see HttpEntity
|
||||
* @since 3.0.2
|
||||
*/
|
||||
HttpResponseMessage<T> PostForMessage<T>(Uri url, object request) where T : class; //throws RestClientException;
|
||||
|
||||
#endregion
|
||||
|
||||
#region PUT
|
||||
|
||||
/**
|
||||
* Create or update a resource by PUTting the given object to the URI.
|
||||
* <p>URI Template variables are expanded using the given URI variables, if any.
|
||||
* <p>The {@code request} parameter can be a {@link HttpEntity} in order to
|
||||
* add additional HTTP headers to the request.
|
||||
* @param url the URL
|
||||
* @param request the Object to be PUT, may be <code>null</code>
|
||||
* @param uriVariables the variables to expand the template
|
||||
* @see HttpEntity
|
||||
*/
|
||||
void Put(string url, object request, params string[] uriVariables); //throws RestClientException;
|
||||
|
||||
/**
|
||||
* Creates a new resource by PUTting the given object to URI template.
|
||||
* <p>URI Template variables are expanded using the given map.
|
||||
* <p>The {@code request} parameter can be a {@link HttpEntity} in order to
|
||||
* add additional HTTP headers to the request.
|
||||
* @param url the URL
|
||||
* @param request the Object to be PUT, may be <code>null</code>
|
||||
* @param uriVariables the variables to expand the template
|
||||
* @see HttpEntity
|
||||
*/
|
||||
void Put(string url, object request, IDictionary<string, string> uriVariables); //throws RestClientException;
|
||||
|
||||
/**
|
||||
* Creates a new resource by PUTting the given object to URL.
|
||||
* <p>The {@code request} parameter can be a {@link HttpEntity} in order to
|
||||
* add additional HTTP headers to the request.
|
||||
* @param url the URL
|
||||
* @param request the Object to be PUT, may be <code>null</code>
|
||||
* @see HttpEntity
|
||||
*/
|
||||
void Put(Uri url, object request); //throws RestClientException;
|
||||
|
||||
#endregion
|
||||
|
||||
#region DELETE
|
||||
|
||||
/**
|
||||
* Delete the resources at the specified URI.
|
||||
* <p>URI Template variables are expanded using the given URI variables, if any.
|
||||
* @param url the URL
|
||||
* @param uriVariables the variables to expand in the template
|
||||
*/
|
||||
void Delete(string url, params string[] uriVariables); //throws RestClientException;
|
||||
|
||||
/**
|
||||
* Delete the resources at the specified URI.
|
||||
* <p>URI Template variables are expanded using the given map.
|
||||
*
|
||||
* @param url the URL
|
||||
* @param uriVariables the variables to expand the template
|
||||
*/
|
||||
void Delete(string url, IDictionary<string, string> uriVariables); //throws RestClientException;
|
||||
|
||||
/**
|
||||
* Delete the resources at the specified URL.
|
||||
* @param url the URL
|
||||
*/
|
||||
void Delete(Uri url); //throws RestClientException;
|
||||
|
||||
#endregion
|
||||
|
||||
#region OPTIONS
|
||||
|
||||
/**
|
||||
* Return the value of the Allow header for the given URI.
|
||||
* <p>URI Template variables are expanded using the given URI variables, if any.
|
||||
* @param url the URL
|
||||
* @param uriVariables the variables to expand in the template
|
||||
* @return the value of the allow header
|
||||
*/
|
||||
IList<HttpMethod> OptionsForAllow(string url, params string[] uriVariables); //throws RestClientException;
|
||||
|
||||
/**
|
||||
* Return the value of the Allow header for the given URI.
|
||||
* <p>URI Template variables are expanded using the given map.
|
||||
* @param url the URL
|
||||
* @param uriVariables the variables to expand in the template
|
||||
* @return the value of the allow header
|
||||
*/
|
||||
IList<HttpMethod> OptionsForAllow(string url, IDictionary<string, string> uriVariables); //throws RestClientException;
|
||||
|
||||
/**
|
||||
* Return the value of the Allow header for the given URL.
|
||||
* @param url the URL
|
||||
* @return the value of the allow header
|
||||
*/
|
||||
IList<HttpMethod> OptionsForAllow(Uri url); //throws RestClientException;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Exchange
|
||||
|
||||
/**
|
||||
* Execute the HTTP method to the given URI template, writing the given request entity to the request, and
|
||||
* returns the response as {@link ResponseEntity}.
|
||||
* <p>URI Template variables are expanded using the given URI variables, if any.
|
||||
* @param url the URL
|
||||
* @param method the HTTP method (GET, POST, etc)
|
||||
* @param requestEntity the entity (headers and/or body) to write to the request, may be {@code null}
|
||||
* @param responseType the type of the return value
|
||||
* @param uriVariables the variables to expand in the template
|
||||
* @return the response as entity
|
||||
* @since 3.0.2
|
||||
*/
|
||||
HttpResponseMessage<T> Exchange<T>(string url, HttpRequestMessage requestMessage, params string[] uriVariables) where T : class; //throws RestClientException;
|
||||
|
||||
/**
|
||||
* Execute the HTTP method to the given URI template, writing the given request entity to the request, and
|
||||
* returns the response as {@link ResponseEntity}.
|
||||
* <p>URI Template variables are expanded using the given URI variables, if any.
|
||||
* @param url the URL
|
||||
* @param method the HTTP method (GET, POST, etc)
|
||||
* @param requestEntity the entity (headers and/or body) to write to the request, may be {@code null}
|
||||
* @param responseType the type of the return value
|
||||
* @param uriVariables the variables to expand in the template
|
||||
* @return the response as entity
|
||||
* @since 3.0.2
|
||||
*/
|
||||
HttpResponseMessage<T> Exchange<T>(string url, HttpRequestMessage requestMessage, IDictionary<string, string> uriVariables) where T : class; //throws RestClientException;
|
||||
|
||||
/**
|
||||
* Execute the HTTP method to the given URI template, writing the given request entity to the request, and
|
||||
* returns the response as {@link ResponseEntity}.
|
||||
* @param url the URL
|
||||
* @param method the HTTP method (GET, POST, etc)
|
||||
* @param requestEntity the entity (headers and/or body) to write to the request, may be {@code null}
|
||||
* @param responseType the type of the return value
|
||||
* @return the response as entity
|
||||
* @since 3.0.2
|
||||
*/
|
||||
HttpResponseMessage<T> Exchange<T>(Uri url, HttpRequestMessage requestMessage) where T : class; //throws RestClientException;
|
||||
|
||||
#endregion
|
||||
|
||||
#region General execution
|
||||
|
||||
/**
|
||||
* Execute the HTTP method to the given URI template, preparing the request with the
|
||||
* {@link RequestCallback}, and reading the response with a {@link ResponseExtractor}.
|
||||
* <p>URI Template variables are expanded using the given URI variables, if any.
|
||||
* @param url the URL
|
||||
* @param method the HTTP method (GET, POST, etc)
|
||||
* @param requestCallback object that prepares the request
|
||||
* @param responseExtractor object that extracts the return value from the response
|
||||
* @param uriVariables the variables to expand in the template
|
||||
* @return an arbitrary object, as returned by the {@link ResponseExtractor}
|
||||
*/
|
||||
T Execute<T>(string url, IRequestCallback requestCallback, IResponseExtractor<T> responseExtractor, params string[] uriVariables) where T : class; //throws RestClientException;
|
||||
|
||||
/**
|
||||
* Execute the HTTP method to the given URI template, preparing the request with the
|
||||
* {@link RequestCallback}, and reading the response with a {@link ResponseExtractor}.
|
||||
* <p>URI Template variables are expanded using the given URI variables map.
|
||||
* @param url the URL
|
||||
* @param method the HTTP method (GET, POST, etc)
|
||||
* @param requestCallback object that prepares the request
|
||||
* @param responseExtractor object that extracts the return value from the response
|
||||
* @param uriVariables the variables to expand in the template
|
||||
* @return an arbitrary object, as returned by the {@link ResponseExtractor}
|
||||
*/
|
||||
T Execute<T>(string url, IRequestCallback requestCallback, IResponseExtractor<T> responseExtractor, IDictionary<string, string> uriVariables) where T : class; //throws RestClientException;
|
||||
|
||||
/**
|
||||
* Execute the HTTP method to the given URL, preparing the request with the
|
||||
* {@link RequestCallback}, and reading the response with a {@link ResponseExtractor}.
|
||||
* @param url the URL
|
||||
* @param method the HTTP method (GET, POST, etc)
|
||||
* @param requestCallback object that prepares the request
|
||||
* @param responseExtractor object that extracts the return value from the response
|
||||
* @return an arbitrary object, as returned by the {@link ResponseExtractor}
|
||||
*/
|
||||
T Execute<T>(Uri url, IRequestCallback requestCallback, IResponseExtractor<T> responseExtractor) where T : class; //throws RestClientException;
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
78
src/Spring/Spring.Http/Http/Rest/RestClientException.cs
Normal file
78
src/Spring/Spring.Http/Http/Rest/RestClientException.cs
Normal file
@@ -0,0 +1,78 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Spring.Http.Rest
|
||||
{
|
||||
[Serializable]
|
||||
public class RestClientException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of the
|
||||
/// RestClientException class.
|
||||
/// </summary>
|
||||
public RestClientException()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the RestClientException class.
|
||||
/// </summary>
|
||||
/// <param name="message">
|
||||
/// A message about the exception.
|
||||
/// </param>
|
||||
public RestClientException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the RestClientException class.
|
||||
/// </summary>
|
||||
/// <param name="message">
|
||||
/// A message about the exception.
|
||||
/// </param>
|
||||
/// <param name="rootCause">
|
||||
/// The root exception that is being wrapped.
|
||||
/// </param>
|
||||
public RestClientException(string message, Exception rootCause)
|
||||
: base(message, rootCause)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the RestClientException class.
|
||||
/// </summary>
|
||||
/// <param name="info">
|
||||
/// The <see cref="System.Runtime.Serialization.SerializationInfo"/>
|
||||
/// that holds the serialized object data about the exception being thrown.
|
||||
/// </param>
|
||||
/// <param name="context">
|
||||
/// The <see cref="System.Runtime.Serialization.StreamingContext"/>
|
||||
/// that contains contextual information about the source or destination.
|
||||
/// </param>
|
||||
protected RestClientException(SerializationInfo info, StreamingContext context)
|
||||
: base(info, context)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
553
src/Spring/Spring.Http/Http/Rest/RestTemplate.cs
Normal file
553
src/Spring/Spring.Http/Http/Rest/RestTemplate.cs
Normal file
@@ -0,0 +1,553 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Spring.Util;
|
||||
using Spring.Http;
|
||||
using Spring.Http.Converters;
|
||||
using Spring.Http.Converters.Xml;
|
||||
using Spring.Http.Converters.Json;
|
||||
using Spring.Http.Converters.Feed;
|
||||
using Spring.Http.Rest.Support;
|
||||
using UriTemplate = Spring.Util.UriTemplate; // UriTemplate in .NET Framework since 3.5
|
||||
|
||||
namespace Spring.Http.Rest
|
||||
{
|
||||
/**
|
||||
* <strong>The central class for client-side HTTP access.</strong> It simplifies communication with HTTP servers, and
|
||||
* enforces RESTful principles. It handles HTTP connections, leaving application code to provide URLs (with possible
|
||||
* template variables) and extract results.
|
||||
*
|
||||
* <p>The main entry points of this template are the methods named after the six main HTTP methods:
|
||||
* <table>
|
||||
* <tr><th>HTTP method</th><th>RestTemplate methods</th></tr>
|
||||
* <tr><td>DELETE</td><td>{@link #delete}</td></tr>
|
||||
* <tr><td>GET</td><td>{@link #getForObject}</td></tr>
|
||||
* <tr><td></td><td>{@link #getForEntity}</td></tr>
|
||||
* <tr><td>HEAD</td><td>{@link #headForHeaders}</td></tr>
|
||||
* <tr><td>OPTIONS</td><td>{@link #optionsForAllow}</td></tr>
|
||||
* <tr><td>POST</td><td>{@link #postForLocation}</td></tr>
|
||||
* <tr><td></td><td>{@link #postForObject}</td></tr>
|
||||
* <tr><td>PUT</td><td>{@link #put}</td></tr>
|
||||
* <tr><td>any</td><td>{@link #exchange}</td></tr>
|
||||
* <tr><td></td><td>{@link #execute}</td></tr> </table>
|
||||
*
|
||||
* <p>For each of these HTTP methods, there are three corresponding Java methods in the {@code RestTemplate}. Two
|
||||
* variant take a {@code String} URI as first argument (eg. {@link #getForObject(String, Class, Object[])}, {@link
|
||||
* #getForObject(String, Class, Map)}), and are capable of substituting any {@linkplain UriTemplate URI templates} in
|
||||
* that URL using either a {@code String} variable arguments array, or a {@code Map<String, String>}. The string varargs
|
||||
* variant expands the given template variables in order, so that
|
||||
* <pre>
|
||||
* String result = restTemplate.getForObject("http://example.com/hotels/{hotel}/bookings/{booking}", String.class,"42",
|
||||
* "21");
|
||||
* </pre>
|
||||
* will perform a GET on {@code http://example.com/hotels/42/bookings/21}. The map variant expands the template based on
|
||||
* variable name, and is therefore more useful when using many variables, or when a single variable is used multiple
|
||||
* times. For example:
|
||||
* <pre>
|
||||
* Map<String, String> vars = Collections.singletonMap("hotel", "42");
|
||||
* String result = restTemplate.getForObject("http://example.com/hotels/{hotel}/rooms/{hotel}", String.class, vars);
|
||||
* </pre>
|
||||
* will perform a GET on {@code http://example.com/hotels/42/rooms/42}. Alternatively, there are {@link URI} variant
|
||||
* methods ({@link #getForObject(URI, Class)}), which do not allow for URI templates, but allow you to reuse a single,
|
||||
* expanded URI multiple times.
|
||||
*
|
||||
* <p>Furthermore, the {@code String}-argument methods assume that the URL String is unencoded. This means that
|
||||
* <pre>
|
||||
* restTemplate.getForObject("http://example.com/hotel list");
|
||||
* </pre>
|
||||
* will perform a GET on {@code http://example.com/hotel%20list}. As a result, any URL passed that is already encoded
|
||||
* will be encoded twice (i.e. {@code http://example.com/hotel%20list} will become {@code
|
||||
* http://example.com/hotel%2520list}). If this behavior is undesirable, use the {@code URI}-argument methods, which
|
||||
* will not perform any URL encoding.
|
||||
*
|
||||
* <p>Objects passed to and returned from these methods are converted to and from HTTP messages by {@link
|
||||
* HttpMessageConverter} instances. Converters for the main mime types are registered by default, but you can also write
|
||||
* your own converter and register it via the {@link #setMessageConverters messageConverters} bean property.
|
||||
*
|
||||
* <p>This template uses a {@link org.springframework.http.client.SimpleClientHttpRequestFactory} and a {@link
|
||||
* DefaultResponseErrorHandler} as default strategies for creating HTTP connections or handling HTTP errors,
|
||||
* respectively. These defaults can be overridden through the {@link #setRequestFactory(ClientHttpRequestFactory)
|
||||
* requestFactory} and {@link #setErrorHandler(ResponseErrorHandler) errorHandler} bean properties.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @see HttpMessageConverter
|
||||
* @see RequestCallback
|
||||
* @see ResponseExtractor
|
||||
* @see ResponseErrorHandler
|
||||
* @since 3.0
|
||||
*/
|
||||
public class RestTemplate : IRestOperations
|
||||
{
|
||||
#region Logging
|
||||
|
||||
private static readonly Common.Logging.ILog LOG = Common.Logging.LogManager.GetLogger(typeof(RestTemplate));
|
||||
|
||||
#endregion
|
||||
|
||||
#region Fields / Properties
|
||||
|
||||
private Uri _baseAddress;
|
||||
private bool _throwExceptionOnError;
|
||||
private IList<IHttpMessageConverter> _messageConverters;
|
||||
private IHttpWebRequestFactory _requestFactory;
|
||||
|
||||
private IResponseExtractor<WebHeaderCollection> headersExtractor;
|
||||
|
||||
|
||||
public Uri BaseAddress
|
||||
{
|
||||
get
|
||||
{
|
||||
return this._baseAddress;
|
||||
}
|
||||
set
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(value, "BaseAddress");
|
||||
if (!value.IsAbsoluteUri)
|
||||
{
|
||||
throw new ArgumentException(String.Format("'{0}' is not an absolute URI", value), "BaseAddress");
|
||||
}
|
||||
this._baseAddress = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool ThrowExceptionOnError
|
||||
{
|
||||
get { return _throwExceptionOnError; }
|
||||
set { _throwExceptionOnError = value; }
|
||||
}
|
||||
|
||||
public IList<IHttpMessageConverter> MessageConverters
|
||||
{
|
||||
get { return this._messageConverters; }
|
||||
set { this._messageConverters = value; }
|
||||
}
|
||||
|
||||
public IHttpWebRequestFactory RequestFactory
|
||||
{
|
||||
get { return this._requestFactory; }
|
||||
set { this._requestFactory = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructor(s)
|
||||
|
||||
public RestTemplate(Uri baseAddress) :
|
||||
this()
|
||||
{
|
||||
this.BaseAddress = baseAddress;
|
||||
}
|
||||
|
||||
public RestTemplate(string baseAddress) :
|
||||
this()
|
||||
{
|
||||
this.BaseAddress = new Uri(baseAddress, UriKind.Absolute);
|
||||
}
|
||||
|
||||
/** Create a new instance of the {@link RestTemplate} using default settings. */
|
||||
public RestTemplate()
|
||||
{
|
||||
this._throwExceptionOnError = true;
|
||||
this.headersExtractor = new HeadersResponseExtractor();
|
||||
this._requestFactory = new DefaultHttpWebRequestFactory();
|
||||
|
||||
this._messageConverters = new List<IHttpMessageConverter>();
|
||||
#if NET_3_5
|
||||
//this._messageConverters.Add(new JsonHttpMessageConverter());
|
||||
this._messageConverters.Add(new Atom10FeedHttpMessageConverter());
|
||||
this._messageConverters.Add(new Rss20FeedHttpMessageConverter());
|
||||
this._messageConverters.Add(new XElementHttpMessageConverter());
|
||||
#endif
|
||||
this._messageConverters.Add(new XmlDocumentHttpMessageConverter());
|
||||
//this._messageConverters.Add(new XmlSerializableHttpMessageConverter());
|
||||
this._messageConverters.Add(new StringHttpMessageConverter());
|
||||
this._messageConverters.Add(new ByteArrayHttpMessageConverter());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IRestOperations Membres
|
||||
|
||||
public T GetForObject<T>(string url, params string[] uriVariables) where T : class
|
||||
{
|
||||
AcceptHeaderRequestCallback requestCallback = new AcceptHeaderRequestCallback(HttpMethod.GET, typeof(T), this._messageConverters);
|
||||
MessageConverterResponseExtractor<T> responseExtractor = new MessageConverterResponseExtractor<T>(this._messageConverters);
|
||||
return this.Execute<T>(url, requestCallback, responseExtractor, uriVariables);
|
||||
}
|
||||
|
||||
public T GetForObject<T>(string url, IDictionary<string, string> uriVariables) where T : class
|
||||
{
|
||||
AcceptHeaderRequestCallback requestCallback = new AcceptHeaderRequestCallback(HttpMethod.GET, typeof(T), this._messageConverters);
|
||||
MessageConverterResponseExtractor<T> responseExtractor = new MessageConverterResponseExtractor<T>(this._messageConverters);
|
||||
return this.Execute<T>(url, requestCallback, responseExtractor, uriVariables);
|
||||
}
|
||||
|
||||
public T GetForObject<T>(Uri url) where T : class
|
||||
{
|
||||
AcceptHeaderRequestCallback requestCallback = new AcceptHeaderRequestCallback(HttpMethod.GET, typeof(T), this._messageConverters);
|
||||
MessageConverterResponseExtractor<T> responseExtractor = new MessageConverterResponseExtractor<T>(this._messageConverters);
|
||||
return this.Execute<T>(url, requestCallback, responseExtractor);
|
||||
}
|
||||
|
||||
public HttpResponseMessage<T> GetForMessage<T>(string url, params string[] uriVariables) where T : class
|
||||
{
|
||||
AcceptHeaderRequestCallback requestCallback = new AcceptHeaderRequestCallback(HttpMethod.GET, typeof(T), this._messageConverters);
|
||||
HttpMessageResponseExtractor<T> responseExtractor = new HttpMessageResponseExtractor<T>(this._messageConverters);
|
||||
return this.Execute<HttpResponseMessage<T>>(url, requestCallback, responseExtractor, uriVariables);
|
||||
}
|
||||
|
||||
public HttpResponseMessage<T> GetForMessage<T>(string url, IDictionary<string, string> uriVariables) where T : class
|
||||
{
|
||||
AcceptHeaderRequestCallback requestCallback = new AcceptHeaderRequestCallback(HttpMethod.GET, typeof(T), this._messageConverters);
|
||||
HttpMessageResponseExtractor<T> responseExtractor = new HttpMessageResponseExtractor<T>(this._messageConverters);
|
||||
return this.Execute<HttpResponseMessage<T>>(url, requestCallback, responseExtractor, uriVariables);
|
||||
}
|
||||
|
||||
public HttpResponseMessage<T> GetForMessage<T>(Uri url) where T : class
|
||||
{
|
||||
AcceptHeaderRequestCallback requestCallback = new AcceptHeaderRequestCallback(HttpMethod.GET, typeof(T), this._messageConverters);
|
||||
HttpMessageResponseExtractor<T> responseExtractor = new HttpMessageResponseExtractor<T>(this._messageConverters);
|
||||
return this.Execute<HttpResponseMessage<T>>(url, requestCallback, responseExtractor);
|
||||
}
|
||||
|
||||
public WebHeaderCollection HeadForHeaders(string url, params string[] uriVariables)
|
||||
{
|
||||
MethodRequestCallback requestCallback = new MethodRequestCallback(HttpMethod.HEAD);
|
||||
return this.Execute<WebHeaderCollection>(url, requestCallback, this.headersExtractor, uriVariables);
|
||||
}
|
||||
|
||||
public WebHeaderCollection HeadForHeaders(string url, IDictionary<string, string> uriVariables)
|
||||
{
|
||||
MethodRequestCallback requestCallback = new MethodRequestCallback(HttpMethod.HEAD);
|
||||
return this.Execute<WebHeaderCollection>(url, requestCallback, this.headersExtractor, uriVariables);
|
||||
}
|
||||
|
||||
public WebHeaderCollection HeadForHeaders(Uri url)
|
||||
{
|
||||
MethodRequestCallback requestCallback = new MethodRequestCallback(HttpMethod.HEAD);
|
||||
return this.Execute<WebHeaderCollection>(url, requestCallback, this.headersExtractor);
|
||||
}
|
||||
|
||||
public Uri PostForLocation(string url, object request, params string[] uriVariables)
|
||||
{
|
||||
HttpMessageRequestCallback requestCallback = new HttpMessageRequestCallback(
|
||||
HttpMethod.POST, request, this._messageConverters);
|
||||
WebHeaderCollection headers = this.Execute<WebHeaderCollection>(
|
||||
url, requestCallback, this.headersExtractor, uriVariables);
|
||||
string location = headers[HttpResponseHeader.Location];
|
||||
return StringUtils.HasText(location) ? new Uri(location) : null;
|
||||
}
|
||||
|
||||
public Uri PostForLocation(string url, object request, IDictionary<string, string> uriVariables)
|
||||
{
|
||||
HttpMessageRequestCallback requestCallback = new HttpMessageRequestCallback(
|
||||
HttpMethod.POST, request, this._messageConverters);
|
||||
WebHeaderCollection headers = this.Execute<WebHeaderCollection>(
|
||||
url, requestCallback, this.headersExtractor, uriVariables);
|
||||
string location = headers[HttpResponseHeader.Location];
|
||||
return StringUtils.HasText(location) ? new Uri(location) : null;
|
||||
}
|
||||
|
||||
public Uri PostForLocation(Uri url, object request)
|
||||
{
|
||||
HttpMessageRequestCallback requestCallback = new HttpMessageRequestCallback(
|
||||
HttpMethod.POST, request, this._messageConverters);
|
||||
WebHeaderCollection headers = this.Execute<WebHeaderCollection>(
|
||||
url, requestCallback, this.headersExtractor);
|
||||
string location = headers[HttpResponseHeader.Location];
|
||||
return StringUtils.HasText(location) ? new Uri(location) : null;
|
||||
}
|
||||
|
||||
public T PostForObject<T>(string url, object request, params string[] uriVariables) where T : class
|
||||
{
|
||||
HttpMessageRequestCallback requestCallback = new HttpMessageRequestCallback(
|
||||
HttpMethod.POST, request, typeof(T), this._messageConverters);
|
||||
MessageConverterResponseExtractor<T> responseExtractor = new MessageConverterResponseExtractor<T>(this._messageConverters);
|
||||
return this.Execute<T>(url, requestCallback, responseExtractor, uriVariables);
|
||||
}
|
||||
|
||||
public T PostForObject<T>(string url, object request, IDictionary<string, string> uriVariables) where T : class
|
||||
{
|
||||
HttpMessageRequestCallback requestCallback = new HttpMessageRequestCallback(
|
||||
HttpMethod.POST, request, typeof(T), this._messageConverters);
|
||||
MessageConverterResponseExtractor<T> responseExtractor = new MessageConverterResponseExtractor<T>(this._messageConverters);
|
||||
return this.Execute<T>(url, requestCallback, responseExtractor, uriVariables);
|
||||
}
|
||||
|
||||
public T PostForObject<T>(Uri url, object request) where T : class
|
||||
{
|
||||
HttpMessageRequestCallback requestCallback = new HttpMessageRequestCallback(
|
||||
HttpMethod.POST, request, typeof(T), this._messageConverters);
|
||||
MessageConverterResponseExtractor<T> responseExtractor = new MessageConverterResponseExtractor<T>(this._messageConverters);
|
||||
return this.Execute<T>(url, requestCallback, responseExtractor);
|
||||
}
|
||||
|
||||
public HttpResponseMessage<T> PostForMessage<T>(string url, object request, params string[] uriVariables) where T : class
|
||||
{
|
||||
HttpMessageRequestCallback requestCallback = new HttpMessageRequestCallback(
|
||||
HttpMethod.POST, request, typeof(T), this._messageConverters);
|
||||
HttpMessageResponseExtractor<T> responseExtractor = new HttpMessageResponseExtractor<T>(this._messageConverters);
|
||||
return this.Execute<HttpResponseMessage<T>>(url, requestCallback, responseExtractor, uriVariables);
|
||||
}
|
||||
|
||||
public HttpResponseMessage<T> PostForMessage<T>(string url, object request, IDictionary<string, string> uriVariables) where T : class
|
||||
{
|
||||
HttpMessageRequestCallback requestCallback = new HttpMessageRequestCallback(
|
||||
HttpMethod.POST, request, typeof(T), this._messageConverters);
|
||||
HttpMessageResponseExtractor<T> responseExtractor = new HttpMessageResponseExtractor<T>(this._messageConverters);
|
||||
return this.Execute<HttpResponseMessage<T>>(url, requestCallback, responseExtractor, uriVariables);
|
||||
}
|
||||
|
||||
public HttpResponseMessage<T> PostForMessage<T>(Uri url, object request) where T : class
|
||||
{
|
||||
HttpMessageRequestCallback requestCallback = new HttpMessageRequestCallback(
|
||||
HttpMethod.POST, request, typeof(T), this._messageConverters);
|
||||
HttpMessageResponseExtractor<T> responseExtractor = new HttpMessageResponseExtractor<T>(this._messageConverters);
|
||||
return this.Execute<HttpResponseMessage<T>>(url, requestCallback, responseExtractor);
|
||||
}
|
||||
|
||||
public void Put(string url, object request, params string[] uriVariables)
|
||||
{
|
||||
HttpMessageRequestCallback requestCallback = new HttpMessageRequestCallback(
|
||||
HttpMethod.PUT, request, this._messageConverters);
|
||||
this.Execute<object>(url, requestCallback, null, uriVariables);
|
||||
}
|
||||
|
||||
public void Put(string url, object request, IDictionary<string, string> uriVariables)
|
||||
{
|
||||
HttpMessageRequestCallback requestCallback = new HttpMessageRequestCallback(
|
||||
HttpMethod.PUT, request, this._messageConverters);
|
||||
this.Execute<object>(url, requestCallback, null, uriVariables);
|
||||
}
|
||||
|
||||
public void Put(Uri url, object request)
|
||||
{
|
||||
HttpMessageRequestCallback requestCallback = new HttpMessageRequestCallback(
|
||||
HttpMethod.PUT, request, this._messageConverters);
|
||||
this.Execute<object>(url, requestCallback, null);
|
||||
}
|
||||
|
||||
public void Delete(string url, params string[] uriVariables)
|
||||
{
|
||||
MethodRequestCallback requestCallback = new MethodRequestCallback(HttpMethod.DELETE);
|
||||
this.Execute<object>(url, requestCallback, null, uriVariables);
|
||||
}
|
||||
|
||||
public void Delete(string url, IDictionary<string, string> uriVariables)
|
||||
{
|
||||
MethodRequestCallback requestCallback = new MethodRequestCallback(HttpMethod.DELETE);
|
||||
this.Execute<object>(url, requestCallback, null, uriVariables);
|
||||
}
|
||||
|
||||
public void Delete(Uri url)
|
||||
{
|
||||
MethodRequestCallback requestCallback = new MethodRequestCallback(HttpMethod.DELETE);
|
||||
this.Execute<object>(url, requestCallback, null);
|
||||
}
|
||||
|
||||
public IList<HttpMethod> OptionsForAllow(string url, params string[] uriVariables)
|
||||
{
|
||||
MethodRequestCallback requestCallback = new MethodRequestCallback(HttpMethod.OPTIONS);
|
||||
WebHeaderCollection headers = this.Execute<WebHeaderCollection>(
|
||||
url, requestCallback, this.headersExtractor, uriVariables);
|
||||
string allow = headers[HttpResponseHeader.Allow];
|
||||
|
||||
return ParseAllowHeader(allow);
|
||||
}
|
||||
|
||||
public IList<HttpMethod> OptionsForAllow(string url, IDictionary<string, string> uriVariables)
|
||||
{
|
||||
MethodRequestCallback requestCallback = new MethodRequestCallback(HttpMethod.OPTIONS);
|
||||
WebHeaderCollection headers = this.Execute<WebHeaderCollection>(url, requestCallback, this.headersExtractor, uriVariables);
|
||||
string allow = headers[HttpResponseHeader.Allow];
|
||||
|
||||
return ParseAllowHeader(allow);
|
||||
}
|
||||
|
||||
public IList<HttpMethod> OptionsForAllow(Uri url)
|
||||
{
|
||||
MethodRequestCallback requestCallback = new MethodRequestCallback(HttpMethod.OPTIONS);
|
||||
WebHeaderCollection headers = this.Execute<WebHeaderCollection>(url, requestCallback, this.headersExtractor);
|
||||
string allow = headers[HttpResponseHeader.Allow];
|
||||
|
||||
return ParseAllowHeader(allow);
|
||||
}
|
||||
|
||||
public HttpResponseMessage<T> Exchange<T>(string url, HttpRequestMessage requestMessage, params string[] uriVariables) where T : class
|
||||
{
|
||||
HttpMessageRequestCallback requestCallback = new HttpMessageRequestCallback(requestMessage, typeof(T), this._messageConverters);
|
||||
HttpMessageResponseExtractor<T> responseExtractor = new HttpMessageResponseExtractor<T>(this._messageConverters);
|
||||
return this.Execute<HttpResponseMessage<T>>(url, requestCallback, responseExtractor, uriVariables);
|
||||
}
|
||||
|
||||
public HttpResponseMessage<T> Exchange<T>(string url, HttpRequestMessage requestMessage, IDictionary<string, string> uriVariables) where T : class
|
||||
{
|
||||
HttpMessageRequestCallback requestCallback = new HttpMessageRequestCallback(requestMessage, typeof(T), this._messageConverters);
|
||||
HttpMessageResponseExtractor<T> responseExtractor = new HttpMessageResponseExtractor<T>(this._messageConverters);
|
||||
return this.Execute<HttpResponseMessage<T>>(url, requestCallback, responseExtractor, uriVariables);
|
||||
}
|
||||
|
||||
public HttpResponseMessage<T> Exchange<T>(Uri url, HttpRequestMessage requestMessage) where T : class
|
||||
{
|
||||
HttpMessageRequestCallback requestCallback = new HttpMessageRequestCallback(requestMessage, typeof(T), this._messageConverters);
|
||||
HttpMessageResponseExtractor<T> responseExtractor = new HttpMessageResponseExtractor<T>(this._messageConverters);
|
||||
return this.Execute<HttpResponseMessage<T>>(url, requestCallback, responseExtractor);
|
||||
}
|
||||
|
||||
public T Execute<T>(string url, IRequestCallback requestCallback, IResponseExtractor<T> responseExtractor, params string[] uriVariables) where T : class
|
||||
{
|
||||
UriTemplate uriTemplate = new UriTemplate(url);
|
||||
Uri uri = uriTemplate.Expand(uriVariables);
|
||||
return this.DoExecute<T>(uri, requestCallback, responseExtractor);
|
||||
}
|
||||
|
||||
public T Execute<T>(string url, IRequestCallback requestCallback, IResponseExtractor<T> responseExtractor, IDictionary<string, string> uriVariables) where T : class
|
||||
{
|
||||
UriTemplate uriTemplate = new UriTemplate(url);
|
||||
Uri uri = uriTemplate.Expand(uriVariables);
|
||||
return this.DoExecute<T>(uri, requestCallback, responseExtractor);
|
||||
}
|
||||
|
||||
public T Execute<T>(Uri url, IRequestCallback requestCallback, IResponseExtractor<T> responseExtractor) where T : class
|
||||
{
|
||||
return this.DoExecute<T>(url, requestCallback, responseExtractor);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/**
|
||||
* Execute the given method on the provided URI. The {@link ClientHttpRequest} is processed using the {@link
|
||||
* RequestCallback}; the response with the {@link ResponseExtractor}.
|
||||
* @param url the fully-expanded URL to connect to
|
||||
* @param method the HTTP method to execute (GET, POST, etc.)
|
||||
* @param requestCallback object that prepares the request (can be <code>null</code>)
|
||||
* @param responseExtractor object that extracts the return value from the response (can be <code>null</code>)
|
||||
* @return an arbitrary object, as returned by the {@link ResponseExtractor}
|
||||
*/
|
||||
protected virtual T DoExecute<T>(Uri url, IRequestCallback requestCallback, IResponseExtractor<T> responseExtractor) where T : class
|
||||
{
|
||||
HttpWebRequest request;
|
||||
HttpWebResponse response = null;
|
||||
|
||||
Uri finalUri = url;
|
||||
if (!url.IsAbsoluteUri)
|
||||
{
|
||||
if (this._baseAddress != null)
|
||||
{
|
||||
finalUri = new Uri(this._baseAddress, url);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException(String.Format("'{0}' is not an absolute URI", url), "url");
|
||||
}
|
||||
}
|
||||
|
||||
// Create and initialize the web request
|
||||
request = this._requestFactory.CreateRequest(finalUri);
|
||||
|
||||
if (requestCallback != null)
|
||||
{
|
||||
requestCallback.DoWithRequest(request);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Get response
|
||||
response = request.GetResponse() as HttpWebResponse;
|
||||
|
||||
if (request.HaveResponse == true && response != null)
|
||||
{
|
||||
#region Instrumentation
|
||||
|
||||
if (LOG.IsDebugEnabled)
|
||||
{
|
||||
LOG.Debug(String.Format(
|
||||
"Request for '{0}' resulted in {1:d} - {1} ({2})",
|
||||
finalUri, response.StatusCode, response.StatusDescription));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
if (responseExtractor != null)
|
||||
{
|
||||
return responseExtractor.ExtractData(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (WebException ex)
|
||||
{
|
||||
// This exception will be raised if the server didn't return 200 - OK
|
||||
// Try to retrieve more information about the network error
|
||||
if (ex.Response != null)
|
||||
{
|
||||
using (HttpWebResponse errorResponse = (HttpWebResponse)ex.Response)
|
||||
{
|
||||
if (this._throwExceptionOnError)
|
||||
{
|
||||
throw new RestClientException(String.Format(
|
||||
"The server returned '{0}' with the status code {1:d} - {1}.",
|
||||
errorResponse.StatusDescription, errorResponse.StatusCode),
|
||||
ex);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (responseExtractor != null)
|
||||
{
|
||||
return responseExtractor.ExtractData(errorResponse);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (response != null)
|
||||
{
|
||||
response.Close();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static IList<HttpMethod> ParseAllowHeader(string allow)
|
||||
{
|
||||
IList<HttpMethod> methods = new List<HttpMethod>();
|
||||
|
||||
if (StringUtils.HasText(allow))
|
||||
{
|
||||
string[] methodsArray = allow.Split(',');
|
||||
|
||||
foreach (string method in methodsArray)
|
||||
{
|
||||
methods.Add((HttpMethod)Enum.Parse(typeof(HttpMethod), method.Trim(), true));
|
||||
}
|
||||
}
|
||||
|
||||
return methods;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Spring.Http;
|
||||
using Spring.Http.Converters;
|
||||
|
||||
namespace Spring.Http.Rest.Support
|
||||
{
|
||||
/**
|
||||
* Request callback implementation that prepares the request's accept headers.
|
||||
*/
|
||||
public class AcceptHeaderRequestCallback : MethodRequestCallback
|
||||
{
|
||||
#region Logging
|
||||
|
||||
private static readonly Common.Logging.ILog LOG = Common.Logging.LogManager.GetLogger(typeof(AcceptHeaderRequestCallback));
|
||||
|
||||
#endregion
|
||||
|
||||
protected Type responseType;
|
||||
protected IList<IHttpMessageConverter> messageConverters;
|
||||
|
||||
public AcceptHeaderRequestCallback(HttpMethod method, Type responseType, IList<IHttpMessageConverter> messageConverters) :
|
||||
base(method)
|
||||
{
|
||||
this.responseType = responseType;
|
||||
this.messageConverters = messageConverters;
|
||||
}
|
||||
|
||||
public override void DoWithRequest(HttpWebRequest request)
|
||||
{
|
||||
base.DoWithRequest(request);
|
||||
|
||||
if (responseType != null)
|
||||
{
|
||||
List<MediaType> allSupportedMediaTypes = new List<MediaType>();
|
||||
foreach (IHttpMessageConverter messageConverter in this.messageConverters)
|
||||
{
|
||||
if (messageConverter.CanRead(responseType, null))
|
||||
{
|
||||
foreach (MediaType supportedMediaType in messageConverter.SupportedMediaTypes)
|
||||
{
|
||||
if (!String.IsNullOrEmpty(supportedMediaType.CharSet))
|
||||
{
|
||||
allSupportedMediaTypes.Add(new MediaType(
|
||||
supportedMediaType.Type, supportedMediaType.Subtype));
|
||||
}
|
||||
else
|
||||
{
|
||||
allSupportedMediaTypes.Add(supportedMediaType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (allSupportedMediaTypes.Count > 0)
|
||||
{
|
||||
MediaType.SortBySpecificity(allSupportedMediaTypes);
|
||||
|
||||
#region Instrumentation
|
||||
|
||||
if (LOG.IsDebugEnabled)
|
||||
{
|
||||
LOG.Debug(String.Format(
|
||||
"Setting request Accept header to '{0}'",
|
||||
MediaType.ToString(allSupportedMediaTypes)));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
request.Accept = MediaType.ToString(allSupportedMediaTypes);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System.Net;
|
||||
|
||||
namespace Spring.Http.Rest.Support
|
||||
{
|
||||
/**
|
||||
* Response extractor that extracts the response {@link HttpHeaders}.
|
||||
*/
|
||||
public class HeadersResponseExtractor : IResponseExtractor<WebHeaderCollection>
|
||||
{
|
||||
public WebHeaderCollection ExtractData(HttpWebResponse response)
|
||||
{
|
||||
return response.Headers;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Spring.Util;
|
||||
using Spring.Http;
|
||||
using Spring.Http.Converters;
|
||||
|
||||
namespace Spring.Http.Rest.Support
|
||||
{
|
||||
/**
|
||||
* Request callback implementation that writes the given object to the request stream.
|
||||
*/
|
||||
public class HttpMessageRequestCallback : AcceptHeaderRequestCallback
|
||||
{
|
||||
#region Logging
|
||||
|
||||
private static readonly Common.Logging.ILog LOG = Common.Logging.LogManager.GetLogger(typeof(HttpMessageRequestCallback));
|
||||
|
||||
#endregion
|
||||
|
||||
private HttpRequestMessage requestMessage;
|
||||
|
||||
public HttpMessageRequestCallback(HttpMethod method, object requestBody, IList<IHttpMessageConverter> messageConverters) :
|
||||
this(method, requestBody, null, messageConverters)
|
||||
{
|
||||
}
|
||||
|
||||
public HttpMessageRequestCallback(HttpMethod method, object requestBody, Type responseType, IList<IHttpMessageConverter> messageConverters) :
|
||||
base(method, responseType, messageConverters)
|
||||
{
|
||||
if (requestBody is HttpRequestMessage)
|
||||
{
|
||||
this.requestMessage = (HttpRequestMessage)requestBody;
|
||||
this.requestMessage.Method = method;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.requestMessage = new HttpRequestMessage(requestBody, method);
|
||||
}
|
||||
}
|
||||
|
||||
public HttpMessageRequestCallback(HttpRequestMessage requestMessage, IList<IHttpMessageConverter> messageConverters) :
|
||||
this(requestMessage, null, messageConverters)
|
||||
{
|
||||
}
|
||||
|
||||
public HttpMessageRequestCallback(HttpRequestMessage requestMessage, Type responseType, IList<IHttpMessageConverter> messageConverters) :
|
||||
base(requestMessage.Method, responseType, messageConverters)
|
||||
{
|
||||
this.requestMessage = requestMessage;
|
||||
}
|
||||
|
||||
public override void DoWithRequest(HttpWebRequest request)
|
||||
{
|
||||
base.DoWithRequest(request);
|
||||
|
||||
// headers
|
||||
if (requestMessage.Headers.Count > 0)
|
||||
{
|
||||
request.Headers.Add(requestMessage.Headers);
|
||||
}
|
||||
|
||||
// body
|
||||
if (requestMessage.Body != null)
|
||||
{
|
||||
object requestBody = requestMessage.Body;
|
||||
MediaType requestContentType = null;
|
||||
if (StringUtils.HasText(requestMessage.Headers[HttpRequestHeader.ContentType]))
|
||||
{
|
||||
requestContentType = MediaType.ParseMediaType(requestMessage.Headers[HttpRequestHeader.ContentType]);
|
||||
}
|
||||
foreach (IHttpMessageConverter messageConverter in base.messageConverters)
|
||||
{
|
||||
if (messageConverter.CanWrite(requestBody.GetType(), requestContentType))
|
||||
{
|
||||
#region Instrumentation
|
||||
|
||||
if (LOG.IsDebugEnabled)
|
||||
{
|
||||
if (requestContentType != null)
|
||||
{
|
||||
LOG.Debug(String.Format(
|
||||
"Writing [{0}] as '{1}' using [{2}]",
|
||||
requestBody, requestContentType, messageConverter));
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG.Debug(String.Format(
|
||||
"Writing [{0}] using [{1}]",
|
||||
requestBody, messageConverter));
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
messageConverter.Write(requestBody, requestContentType, request);
|
||||
return;
|
||||
}
|
||||
}
|
||||
string message = String.Format(
|
||||
"Could not write request: no suitable IHttpMessageConverter found for request type [{0}]",
|
||||
requestBody.GetType().FullName);
|
||||
if (requestContentType != null)
|
||||
{
|
||||
message = String.Format("{0} and content type [{1}]", message, requestContentType);
|
||||
}
|
||||
throw new RestClientException(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System.Net;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Spring.Util;
|
||||
using Spring.Http;
|
||||
using Spring.Http.Converters;
|
||||
|
||||
namespace Spring.Http.Rest.Support
|
||||
{
|
||||
/**
|
||||
* Response extractor for {@link HttpEntity}.
|
||||
*/
|
||||
public class HttpMessageResponseExtractor<T> : IResponseExtractor<HttpResponseMessage<T>> where T : class
|
||||
{
|
||||
private MessageConverterResponseExtractor<T> httpMessageConverterExtractor;
|
||||
|
||||
public HttpMessageResponseExtractor(IList<IHttpMessageConverter> messageConverters)
|
||||
{
|
||||
httpMessageConverterExtractor = new MessageConverterResponseExtractor<T>(messageConverters);
|
||||
}
|
||||
|
||||
public HttpResponseMessage<T> ExtractData(HttpWebResponse response)
|
||||
{
|
||||
if (StringUtils.HasText(response.Headers[HttpResponseHeader.ContentType]))
|
||||
{
|
||||
T body = httpMessageConverterExtractor.ExtractData(response);
|
||||
return new HttpResponseMessage<T>(body, response.Headers, response.StatusCode, response.StatusDescription);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new HttpResponseMessage<T>(response.Headers, response.StatusCode, response.StatusDescription);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Spring.Util;
|
||||
using Spring.Http;
|
||||
using Spring.Http.Converters;
|
||||
|
||||
namespace Spring.Http.Rest.Support
|
||||
{
|
||||
/**
|
||||
* Response extractor that uses the given {@linkplain HttpMessageConverter entity converters} to convert the response
|
||||
* into a type <code>T</code>.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @see RestTemplate
|
||||
* @since 3.0
|
||||
*/
|
||||
public class MessageConverterResponseExtractor<T> : IResponseExtractor<T> where T : class
|
||||
{
|
||||
#region Logging
|
||||
|
||||
private static readonly Common.Logging.ILog LOG = Common.Logging.LogManager.GetLogger(typeof(MessageConverterResponseExtractor<T>));
|
||||
|
||||
#endregion
|
||||
|
||||
private IList<IHttpMessageConverter> messageConverters;
|
||||
|
||||
/**
|
||||
* Creates a new instance of the {@code HttpMessageConverterExtractor} with the given response type and message
|
||||
* converters. The given converters must support the response type.
|
||||
*/
|
||||
public MessageConverterResponseExtractor(IList<IHttpMessageConverter> messageConverters)
|
||||
{
|
||||
this.messageConverters = messageConverters;
|
||||
}
|
||||
|
||||
public T ExtractData(HttpWebResponse response)
|
||||
{
|
||||
if (!StringUtils.HasText(response.Headers[HttpResponseHeader.ContentType]))
|
||||
{
|
||||
throw new RestClientException("Could not extract response: no Content-Type found");
|
||||
}
|
||||
MediaType contentType = MediaType.ParseMediaType(response.Headers[HttpResponseHeader.ContentType]);
|
||||
foreach(IHttpMessageConverter messageConverter in messageConverters)
|
||||
{
|
||||
if (messageConverter.CanRead(typeof(T), contentType))
|
||||
{
|
||||
#region Instrumentation
|
||||
|
||||
if (LOG.IsDebugEnabled)
|
||||
{
|
||||
LOG.Debug(String.Format(
|
||||
"Reading [{0}] as '{1}' using [{2}]",
|
||||
typeof(T).FullName, contentType, messageConverter));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
return messageConverter.Read<T>(response);
|
||||
}
|
||||
}
|
||||
throw new RestClientException(String.Format(
|
||||
"Could not extract response: no suitable HttpMessageConverter found for response type [{0}] and content type [{1}]",
|
||||
typeof(T).FullName, contentType));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
|
||||
using Spring.Http;
|
||||
|
||||
namespace Spring.Http.Rest.Support
|
||||
{
|
||||
/**
|
||||
* Request callback implementation that sets the Http method.
|
||||
*/
|
||||
public class MethodRequestCallback : IRequestCallback
|
||||
{
|
||||
#region Logging
|
||||
|
||||
private static readonly Common.Logging.ILog LOG = Common.Logging.LogManager.GetLogger(typeof(MethodRequestCallback));
|
||||
|
||||
#endregion
|
||||
|
||||
protected HttpMethod method;
|
||||
|
||||
public MethodRequestCallback(HttpMethod method)
|
||||
{
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
public virtual void DoWithRequest(HttpWebRequest request)
|
||||
{
|
||||
#region Instrumentation
|
||||
|
||||
if (LOG.IsDebugEnabled)
|
||||
{
|
||||
LOG.Debug(String.Format("Setting request Method to '{0}'", this.method));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
request.Method = this.method.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
146
src/Spring/Spring.Http/Spring.Http.2008.csproj
Normal file
146
src/Spring/Spring.Http/Spring.Http.2008.csproj
Normal file
@@ -0,0 +1,146 @@
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
|
||||
<PropertyGroup>
|
||||
<ProjectType>Local</ProjectType>
|
||||
<ProductVersion>9.0.30729</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{FAC04F79-4B1F-1D13-B30F-00EE04EC0FBC}</ProjectGuid>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ApplicationIcon>
|
||||
</ApplicationIcon>
|
||||
<AssemblyKeyContainerName>
|
||||
</AssemblyKeyContainerName>
|
||||
<AssemblyName>Spring.Http</AssemblyName>
|
||||
<AssemblyOriginatorKeyFile>
|
||||
</AssemblyOriginatorKeyFile>
|
||||
<DefaultClientScript>JScript</DefaultClientScript>
|
||||
<DefaultHTMLPageLayout>Grid</DefaultHTMLPageLayout>
|
||||
<DefaultTargetSchema>IE50</DefaultTargetSchema>
|
||||
<DelaySign>false</DelaySign>
|
||||
<OutputType>Library</OutputType>
|
||||
<RootNamespace>Spring</RootNamespace>
|
||||
<RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
|
||||
<StartupObject>
|
||||
</StartupObject>
|
||||
<SignAssembly>false</SignAssembly>
|
||||
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||
<TargetFrameworkSubset>
|
||||
</TargetFrameworkSubset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<OutputPath>..\..\..\build\VS.Net.2008\Spring.Http\Debug\</OutputPath>
|
||||
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
|
||||
<BaseAddress>285212672</BaseAddress>
|
||||
<CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
|
||||
<ConfigurationOverrideFile>
|
||||
</ConfigurationOverrideFile>
|
||||
<DefineConstants>TRACE;DEBUG;NET_2_0;NET_3_0;NET_3_5</DefineConstants>
|
||||
<DocumentationFile>Spring.Http.xml</DocumentationFile>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<FileAlignment>4096</FileAlignment>
|
||||
<NoStdLib>false</NoStdLib>
|
||||
<NoWarn>
|
||||
</NoWarn>
|
||||
<Optimize>false</Optimize>
|
||||
<RegisterForComInterop>false</RegisterForComInterop>
|
||||
<RemoveIntegerChecks>false</RemoveIntegerChecks>
|
||||
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<DebugType>full</DebugType>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<OutputPath>..\..\..\build\VS.Net.2008\Spring.Http\Release\</OutputPath>
|
||||
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
|
||||
<BaseAddress>285212672</BaseAddress>
|
||||
<CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
|
||||
<ConfigurationOverrideFile>
|
||||
</ConfigurationOverrideFile>
|
||||
<DefineConstants>TRACE;NET_2_0;NET_3_0;NET_3_5</DefineConstants>
|
||||
<DocumentationFile>
|
||||
</DocumentationFile>
|
||||
<DebugSymbols>false</DebugSymbols>
|
||||
<FileAlignment>4096</FileAlignment>
|
||||
<NoStdLib>false</NoStdLib>
|
||||
<NoWarn>
|
||||
</NoWarn>
|
||||
<Optimize>true</Optimize>
|
||||
<RegisterForComInterop>false</RegisterForComInterop>
|
||||
<RemoveIntegerChecks>false</RemoveIntegerChecks>
|
||||
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<DebugType>none</DebugType>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Common.Logging, Version=2.1.0.0, Culture=neutral, PublicKeyToken=65e474d141e25e07, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\lib\Net\2.0\Common.Logging.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System">
|
||||
<Name>System</Name>
|
||||
</Reference>
|
||||
<Reference Include="System.Configuration" />
|
||||
<Reference Include="System.Runtime.Serialization">
|
||||
<RequiredTargetFramework>3.0</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="System.ServiceModel.Web">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="System.Xml.Linq">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="..\CommonAssemblyInfo.cs">
|
||||
<Link>CommonAssemblyInfo.cs</Link>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="AssemblyInfo.cs" />
|
||||
<Compile Include="Http\Converters\Feed\Atom10FeedHttpMessageConverter.cs" />
|
||||
<Compile Include="Http\Converters\Feed\AbstractFeedHttpMessageConverter.cs" />
|
||||
<Compile Include="Http\Converters\Feed\RssFeedHttpMessageConverter.cs" />
|
||||
<Compile Include="Http\Converters\Json\JsonHttpMessageConverter.cs" />
|
||||
<Compile Include="Http\Converters\Xml\AbstractXmlHttpMessageConverter.cs" />
|
||||
<Compile Include="Http\Converters\Xml\XElementHttpMessageConverter.cs" />
|
||||
<Compile Include="Http\Converters\Xml\XmlDocumentHttpMessageConverter.cs" />
|
||||
<Compile Include="Http\Converters\Xml\XmlSerializableHttpMessageConverter.cs" />
|
||||
<Compile Include="Http\Converters\Xml\DataContractHttpMessageConverter.cs" />
|
||||
<Compile Include="Http\DefaultHttpWebRequestFactory.cs" />
|
||||
<Compile Include="Http\HttpResponseMessage.cs" />
|
||||
<Compile Include="Http\IHttpWebRequestFactory.cs" />
|
||||
<Compile Include="Http\HttpRequestMessage.cs" />
|
||||
<Compile Include="Http\Rest\Support\AcceptHeaderRequestCallback.cs" />
|
||||
<Compile Include="Http\Rest\Support\MethodRequestCallback.cs" />
|
||||
<Compile Include="Http\Rest\Support\HttpMessageRequestCallback.cs" />
|
||||
<Compile Include="Http\Rest\Support\HeadersResponseExtractor.cs" />
|
||||
<Compile Include="Http\Rest\Support\HttpMessageResponseExtractor.cs" />
|
||||
<Compile Include="Http\Converters\AbstractHttpMessageConverter.cs" />
|
||||
<Compile Include="Http\Converters\ByteArrayHttpMessageConverter.cs" />
|
||||
<Compile Include="Http\Rest\Support\MessageConverterResponseExtractor.cs" />
|
||||
<Compile Include="Http\HttpMethod.cs" />
|
||||
<Compile Include="Http\Converters\IHttpMessageConverter.cs" />
|
||||
<Compile Include="Http\Rest\IRequestCallback.cs" />
|
||||
<Compile Include="Http\Rest\IResponseExtractor.cs" />
|
||||
<Compile Include="Http\Rest\IRestOperations.cs" />
|
||||
<Compile Include="Http\MediaType.cs" />
|
||||
<Compile Include="Http\Rest\RestClientException.cs" />
|
||||
<Compile Include="Http\Rest\RestTemplate.cs" />
|
||||
<Compile Include="Http\Converters\StringHttpMessageConverter.cs" />
|
||||
<Compile Include="Util\UriTemplate.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Spring.Core\Spring.Core.2008.csproj">
|
||||
<Project>{710961A3-0DF4-49E4-A26E-F5B9C044AC84}</Project>
|
||||
<Name>Spring.Core.2008</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PreBuildEvent>
|
||||
</PreBuildEvent>
|
||||
<PostBuildEvent>
|
||||
</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
184
src/Spring/Spring.Http/Spring.Http.2010.csproj
Normal file
184
src/Spring/Spring.Http/Spring.Http.2010.csproj
Normal file
@@ -0,0 +1,184 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
|
||||
<PropertyGroup>
|
||||
<ProjectType>Local</ProjectType>
|
||||
<ProductVersion>9.0.30729</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectGuid>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ApplicationIcon>
|
||||
</ApplicationIcon>
|
||||
<AssemblyKeyContainerName>
|
||||
</AssemblyKeyContainerName>
|
||||
<AssemblyName>Spring.Http</AssemblyName>
|
||||
<AssemblyOriginatorKeyFile>
|
||||
</AssemblyOriginatorKeyFile>
|
||||
<DefaultClientScript>JScript</DefaultClientScript>
|
||||
<DefaultHTMLPageLayout>Grid</DefaultHTMLPageLayout>
|
||||
<DefaultTargetSchema>IE50</DefaultTargetSchema>
|
||||
<DelaySign>false</DelaySign>
|
||||
<OutputType>Library</OutputType>
|
||||
<RootNamespace>Spring</RootNamespace>
|
||||
<RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
|
||||
<StartupObject>
|
||||
</StartupObject>
|
||||
<SignAssembly>false</SignAssembly>
|
||||
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||
<FileUpgradeFlags>
|
||||
</FileUpgradeFlags>
|
||||
<OldToolsVersion>3.5</OldToolsVersion>
|
||||
<UpgradeBackupLocation />
|
||||
<TargetFrameworkProfile />
|
||||
<PublishUrl>publish\</PublishUrl>
|
||||
<Install>true</Install>
|
||||
<InstallFrom>Disk</InstallFrom>
|
||||
<UpdateEnabled>false</UpdateEnabled>
|
||||
<UpdateMode>Foreground</UpdateMode>
|
||||
<UpdateInterval>7</UpdateInterval>
|
||||
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
|
||||
<UpdatePeriodically>false</UpdatePeriodically>
|
||||
<UpdateRequired>false</UpdateRequired>
|
||||
<MapFileExtensions>true</MapFileExtensions>
|
||||
<ApplicationRevision>0</ApplicationRevision>
|
||||
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
|
||||
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||
<UseApplicationTrust>false</UseApplicationTrust>
|
||||
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<OutputPath>..\..\..\build\VS.Net.2010\Spring.Http\Debug\</OutputPath>
|
||||
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
|
||||
<BaseAddress>285212672</BaseAddress>
|
||||
<CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
|
||||
<ConfigurationOverrideFile>
|
||||
</ConfigurationOverrideFile>
|
||||
<DefineConstants>TRACE;DEBUG;NET_2_0;NET_3_0;NET_3_5</DefineConstants>
|
||||
<DocumentationFile>Spring.Http.xml</DocumentationFile>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<FileAlignment>4096</FileAlignment>
|
||||
<NoStdLib>false</NoStdLib>
|
||||
<NoWarn>
|
||||
</NoWarn>
|
||||
<Optimize>false</Optimize>
|
||||
<RegisterForComInterop>false</RegisterForComInterop>
|
||||
<RemoveIntegerChecks>false</RemoveIntegerChecks>
|
||||
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<DebugType>full</DebugType>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<OutputPath>..\..\..\build\VS.Net.2010\Spring.Http\Release\</OutputPath>
|
||||
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
|
||||
<BaseAddress>285212672</BaseAddress>
|
||||
<CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
|
||||
<ConfigurationOverrideFile>
|
||||
</ConfigurationOverrideFile>
|
||||
<DefineConstants>TRACE;NET_2_0;NET_3_0;NET_3_5</DefineConstants>
|
||||
<DocumentationFile>
|
||||
</DocumentationFile>
|
||||
<DebugSymbols>false</DebugSymbols>
|
||||
<FileAlignment>4096</FileAlignment>
|
||||
<NoStdLib>false</NoStdLib>
|
||||
<NoWarn>
|
||||
</NoWarn>
|
||||
<Optimize>true</Optimize>
|
||||
<RegisterForComInterop>false</RegisterForComInterop>
|
||||
<RemoveIntegerChecks>false</RemoveIntegerChecks>
|
||||
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<DebugType>none</DebugType>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Common.Logging, Version=2.1.0.0, Culture=neutral, PublicKeyToken=65e474d141e25e07, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\lib\Net\2.0\Common.Logging.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System">
|
||||
<Name>System</Name>
|
||||
</Reference>
|
||||
<Reference Include="System.configuration" />
|
||||
<Reference Include="System.Runtime.Serialization" />
|
||||
<Reference Include="System.ServiceModel.Web" />
|
||||
<Reference Include="System.XML" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="..\CommonAssemblyInfo.cs">
|
||||
<Link>CommonAssemblyInfo.cs</Link>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="AssemblyInfo.cs" />
|
||||
<Compile Include="Http\HttpResponseMessage.cs" />
|
||||
<Compile Include="Http\DefaultHttpWebRequestFactory.cs" />
|
||||
<Compile Include="Http\Converters\AbstractHttpMessageConverter.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Http\Converters\ByteArrayHttpMessageConverter.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Http\Converters\Feed\AbstractFeedHttpMessageConverter.cs" />
|
||||
<Compile Include="Http\Converters\Feed\Atom10FeedHttpMessageConverter.cs" />
|
||||
<Compile Include="Http\Converters\Feed\RssFeedHttpMessageConverter.cs" />
|
||||
<Compile Include="Http\Converters\IHttpMessageConverter.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Http\Converters\Json\JsonHttpMessageConverter.cs" />
|
||||
<Compile Include="Http\Converters\StringHttpMessageConverter.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Http\Converters\Xml\AbstractXmlHttpMessageConverter.cs" />
|
||||
<Compile Include="Http\Converters\Xml\DataContractHttpMessageConverter.cs" />
|
||||
<Compile Include="Http\Converters\Xml\XElementHttpMessageConverter.cs" />
|
||||
<Compile Include="Http\Converters\Xml\XmlDocumentHttpMessageConverter.cs" />
|
||||
<Compile Include="Http\Converters\Xml\XmlSerializableHttpMessageConverter.cs" />
|
||||
<Compile Include="Http\HttpMethod.cs" />
|
||||
<Compile Include="Http\HttpRequestMessage.cs" />
|
||||
<Compile Include="Http\IHttpWebRequestFactory.cs" />
|
||||
<Compile Include="Http\MediaType.cs" />
|
||||
<Compile Include="Http\Rest\IRequestCallback.cs" />
|
||||
<Compile Include="Http\Rest\IResponseExtractor.cs" />
|
||||
<Compile Include="Http\Rest\IRestOperations.cs" />
|
||||
<Compile Include="Http\Rest\RestClientException.cs" />
|
||||
<Compile Include="Http\Rest\RestTemplate.cs" />
|
||||
<Compile Include="Http\Rest\Support\AcceptHeaderRequestCallback.cs" />
|
||||
<Compile Include="Http\Rest\Support\HeadersResponseExtractor.cs" />
|
||||
<Compile Include="Http\Rest\Support\HttpMessageRequestCallback.cs" />
|
||||
<Compile Include="Http\Rest\Support\HttpMessageResponseExtractor.cs" />
|
||||
<Compile Include="Http\Rest\Support\MessageConverterResponseExtractor.cs" />
|
||||
<Compile Include="Http\Rest\Support\MethodRequestCallback.cs" />
|
||||
<Compile Include="Util\UriTemplate.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Spring.Core\Spring.Core.2010.csproj">
|
||||
<Project>{710961A3-0DF4-49E4-A26E-F5B9C044AC84}</Project>
|
||||
<Name>Spring.Core.2010</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
|
||||
<Install>false</Install>
|
||||
</BootstrapperPackage>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>.NET Framework 3.5 SP1</ProductName>
|
||||
<Install>true</Install>
|
||||
</BootstrapperPackage>
|
||||
<BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>Windows Installer 3.1</ProductName>
|
||||
<Install>true</Install>
|
||||
</BootstrapperPackage>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PreBuildEvent>
|
||||
</PreBuildEvent>
|
||||
<PostBuildEvent>
|
||||
</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
239
src/Spring/Spring.Http/Util/UriTemplate.cs
Normal file
239
src/Spring/Spring.Http/Util/UriTemplate.cs
Normal file
@@ -0,0 +1,239 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Spring.Util
|
||||
{
|
||||
// TODO : Check .NET 3.5 class
|
||||
// TODO : Back to original Java behavior Expand(params string[]) method ?
|
||||
|
||||
/**
|
||||
* Represents a URI template. An URI template is a URI-like String that contained variables marked of in braces
|
||||
* (<code>{</code>, <code>}</code>), which can be expanded to produce a URI. <p>See {@link #expand(Map)},
|
||||
* {@link #expand(Object[])}, and {@link #match(String)} for example usages.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
* @see <a href="http://bitworking.org/projects/URI-Templates/">URI Templates</a>
|
||||
*/
|
||||
public class UriTemplate
|
||||
{
|
||||
/** Captures URI template variable names. */
|
||||
private static Regex VARIABLENAMES_REGEX = new Regex(@"\{([^/]+?)\}", RegexOptions.Compiled);
|
||||
//private static Regex VARIABLENAMES_REGEX = new Regex(@"\{[^{}]+\}", RegexOptions.Compiled);
|
||||
|
||||
/** Replaces template variables in the URI template. */
|
||||
private static string VARIABLEVALUE_PATTERN = "(?<{0}>.*)";
|
||||
|
||||
private const string BRACE_LEFT = "{";
|
||||
private const string BRACE_RIGHT = "}";
|
||||
|
||||
private string uriTemplate;
|
||||
private string[] variableNames;
|
||||
private Regex matchRegex;
|
||||
|
||||
public string[] VariableNames
|
||||
{
|
||||
get { return this.variableNames; }
|
||||
}
|
||||
|
||||
public UriTemplate(string uriTemplate)
|
||||
{
|
||||
this.uriTemplate = uriTemplate;
|
||||
Parser parser = new Parser(uriTemplate);
|
||||
this.variableNames = parser.GetVariableNames();
|
||||
this.matchRegex = parser.GetMatchRegex();
|
||||
}
|
||||
|
||||
public Uri Expand(IDictionary<string, string> uriVariables)
|
||||
{
|
||||
if (uriVariables.Count != this.variableNames.Length)
|
||||
{
|
||||
throw new ArgumentException(String.Format(
|
||||
"Invalid amount of variables values in '{0}': expected {1}; got {2}",
|
||||
this.uriTemplate, this.variableNames.Length, uriVariables.Count));
|
||||
}
|
||||
|
||||
string uri = this.uriTemplate;
|
||||
foreach (string variableName in this.variableNames)
|
||||
{
|
||||
if (!uriVariables.ContainsKey(variableName))
|
||||
{
|
||||
throw new ArgumentException(String.Format(
|
||||
"'uriVariables' dictionary has no value for '{0}'",
|
||||
variableName));
|
||||
}
|
||||
uri = Replace(uri, variableName, uriVariables[variableName]);
|
||||
}
|
||||
|
||||
return new Uri(uri, UriKind.RelativeOrAbsolute);
|
||||
|
||||
//string[] uriVariableValues = new String[this.variableNames.Length];
|
||||
//for (int i = 0; i < this.variableNames.Length; i++)
|
||||
//{
|
||||
// string variableName = this.variableNames[i];
|
||||
// if (!uriVariables.ContainsKey(variableName))
|
||||
// {
|
||||
// throw new ArgumentException(String.Format(
|
||||
// "'uriVariables' dictionary has no value for '{0}'",
|
||||
// variableName));
|
||||
// }
|
||||
// uriVariableValues[i] = uriVariables[variableName];
|
||||
//}
|
||||
//return Expand(uriVariableValues);
|
||||
}
|
||||
|
||||
public Uri Expand(params string[] uriVariableValues)
|
||||
{
|
||||
if (uriVariableValues.Length != this.variableNames.Length)
|
||||
{
|
||||
throw new ArgumentException(String.Format(
|
||||
"Invalid amount of variables values in '{0}': expected {1}; got {2}",
|
||||
this.uriTemplate, this.variableNames.Length, uriVariableValues.Length));
|
||||
}
|
||||
|
||||
string uri = this.uriTemplate;
|
||||
for (int i = 0; i < this.variableNames.Length; i++)
|
||||
{
|
||||
uri = Replace(uri, this.variableNames[i], uriVariableValues[i]);
|
||||
}
|
||||
|
||||
return new Uri(uri, UriKind.RelativeOrAbsolute);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate whether the given URI matches this template.
|
||||
* @param uri the URI to match to
|
||||
* @return <code>true</code> if it matches; <code>false</code> otherwise
|
||||
*/
|
||||
public bool Matches(string uri)
|
||||
{
|
||||
if (uri == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return this.matchRegex.IsMatch(uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* Match the given URI to a map of variable values. Keys in the returned map are variable names, values are variable
|
||||
* values, as occurred in the given URI. <p>Example: <pre class="code"> UriTemplate template = new
|
||||
* UriTemplate("http://example.com/hotels/{hotel}/bookings/{booking}"); System.out.println(template.match("http://example.com/hotels/1/bookings/42"));
|
||||
* </pre> will print: <blockquote><code>{hotel=1, booking=42}</code></blockquote>
|
||||
* @param uri the URI to match to
|
||||
* @return a map of variable values
|
||||
*/
|
||||
public IDictionary<string, string> Match(string uri)
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(uri, "uri");
|
||||
|
||||
IDictionary<string, string> result = new Dictionary<string, string>();
|
||||
Match match = this.matchRegex.Match(uri);
|
||||
for (int i = 1; i < match.Groups.Count; i++ )
|
||||
{
|
||||
result.Add(this.matchRegex.GroupNameFromNumber(i), match.Groups[i].Value);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return this.uriTemplate;
|
||||
}
|
||||
|
||||
//private static string[] GetVariableNames(string uriTemplate)
|
||||
//{
|
||||
// List<string> variableNames = new List<string>();
|
||||
// foreach (Match match in VARIABLENAMES_REGEX.Matches(uriTemplate))
|
||||
// {
|
||||
// string token = match.Value;
|
||||
// token = token.Substring(1, token.Length - 2);
|
||||
|
||||
// if (!variableNames.Contains(token))
|
||||
// {
|
||||
// variableNames.Add(token);
|
||||
// }
|
||||
// }
|
||||
|
||||
// return variableNames.ToArray();
|
||||
//}
|
||||
|
||||
private static string Replace(string uriTemplate, string token, string value)
|
||||
{
|
||||
string quotedToken = BRACE_LEFT + token + BRACE_RIGHT;
|
||||
return uriTemplate.Replace(quotedToken, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Static inner class to parse uri template strings into a matching regular expression.
|
||||
*/
|
||||
private class Parser
|
||||
{
|
||||
private List<String> variableNames = new List<String>();
|
||||
private StringBuilder patternBuilder = new StringBuilder();
|
||||
|
||||
public Parser(string uriTemplate)
|
||||
{
|
||||
AssertUtils.ArgumentHasText(uriTemplate, "'uriTemplate' must not be null");
|
||||
|
||||
int index = 0;
|
||||
this.patternBuilder.Append("^");
|
||||
foreach (Match match in VARIABLENAMES_REGEX.Matches(uriTemplate))
|
||||
{
|
||||
string variableName = match.Groups[1].Value;
|
||||
if (!variableNames.Contains(variableName))
|
||||
{
|
||||
variableNames.Add(variableName);
|
||||
}
|
||||
|
||||
this.patternBuilder.Append(Escape(uriTemplate, index, match.Index - index));
|
||||
this.patternBuilder.Append(String.Format(VARIABLEVALUE_PATTERN, variableName));
|
||||
index = match.Index + match.Length;
|
||||
}
|
||||
this.patternBuilder.Append(Escape(uriTemplate, index, uriTemplate.Length - index));
|
||||
this.patternBuilder.Append("$");
|
||||
}
|
||||
|
||||
private static string Escape(String fullPath, int start, int end)
|
||||
{
|
||||
if (start == end)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
return Regex.Escape(fullPath.Substring(start, end));
|
||||
}
|
||||
|
||||
public string[] GetVariableNames()
|
||||
{
|
||||
return this.variableNames.ToArray();
|
||||
}
|
||||
|
||||
public Regex GetMatchRegex()
|
||||
{
|
||||
return new Regex(this.patternBuilder.ToString(), RegexOptions.Compiled);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
25
test/Spring/Spring.Http.Tests/AssemblyInfo.cs
Normal file
25
test/Spring/Spring.Http.Tests/AssemblyInfo.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: AssemblyTitle("Spring.Http Tests")]
|
||||
[assembly: AssemblyDescription("Unit tests for Spring.Http assembly")]
|
||||
@@ -0,0 +1,99 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
|
||||
using NUnit.Framework;
|
||||
using Rhino.Mocks;
|
||||
|
||||
namespace Spring.Http.Converters
|
||||
{
|
||||
/// <summary>
|
||||
/// Unit tests for the ByteArrayHttpMessageConverter class.
|
||||
/// </summary>
|
||||
/// <author>Arjen Poutsma</author>
|
||||
/// <author>Bruno Baia (.NET)</author>
|
||||
[TestFixture]
|
||||
public class ByteArrayHttpMessageConverterTests
|
||||
{
|
||||
private ByteArrayHttpMessageConverter converter;
|
||||
private MockRepository mocks;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
mocks = new MockRepository();
|
||||
converter = new ByteArrayHttpMessageConverter();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanRead()
|
||||
{
|
||||
Assert.IsTrue(converter.CanRead(typeof(byte[]), new MediaType("application", "octet-stream")));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanWrite()
|
||||
{
|
||||
Assert.IsTrue(converter.CanWrite(typeof(byte[]), new MediaType("application", "octet-stream")));
|
||||
Assert.IsTrue(converter.CanWrite(typeof(byte[]), MediaType.ALL));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Read()
|
||||
{
|
||||
byte[] body = new byte[] { 0x1, 0x2 };
|
||||
|
||||
HttpWebResponse webResponse = mocks.CreateMock<HttpWebResponse>();
|
||||
Expect.Call<Stream>(webResponse.GetResponseStream()).Return(new MemoryStream(body)).Repeat.Once();
|
||||
Expect.Call<long>(webResponse.ContentLength).Return(2).Repeat.Once();
|
||||
|
||||
mocks.ReplayAll();
|
||||
|
||||
byte[] result = converter.Read<byte[]>(webResponse);
|
||||
Assert.AreEqual(body.Length, result.Length, "Invalid result");
|
||||
Assert.AreEqual(body[0], result[0], "Invalid result");
|
||||
Assert.AreEqual(body[1], result[1], "Invalid result");
|
||||
|
||||
mocks.VerifyAll();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Write()
|
||||
{
|
||||
byte[] body = new byte[] { 0x1, 0x2 };
|
||||
|
||||
HttpWebRequest webRequest = WebRequest.Create("http://localhost") as HttpWebRequest;
|
||||
webRequest.Method = "POST";
|
||||
|
||||
converter.Write(body, null, webRequest);
|
||||
|
||||
using (Stream postStream = webRequest.GetRequestStream())
|
||||
{
|
||||
//Assert.AreEqual(body.Length, postStream.Length, "Invalid result");
|
||||
}
|
||||
|
||||
Assert.AreEqual(new MediaType("application", "octet-stream"), MediaType.ParseMediaType(webRequest.ContentType), "Invalid content-type");
|
||||
Assert.AreEqual(2, webRequest.ContentLength, "Invalid content-length");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
|
||||
using NUnit.Framework;
|
||||
using Rhino.Mocks;
|
||||
|
||||
namespace Spring.Http.Converters
|
||||
{
|
||||
/// <summary>
|
||||
/// Unit tests for the StringHttpMessageConverter class.
|
||||
/// </summary>
|
||||
/// <author>Arjen Poutsma</author>
|
||||
/// <author>Bruno Baia (.NET)</author>
|
||||
[TestFixture]
|
||||
public class StringHttpMessageConverterTests
|
||||
{
|
||||
private StringHttpMessageConverter converter;
|
||||
private MockRepository mocks;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
mocks = new MockRepository();
|
||||
converter = new StringHttpMessageConverter();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanRead()
|
||||
{
|
||||
Assert.IsTrue(converter.CanRead(typeof(string), new MediaType("text", "plain")));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanWrite()
|
||||
{
|
||||
Assert.IsTrue(converter.CanWrite(typeof(string), new MediaType("text", "plain")));
|
||||
Assert.IsTrue(converter.CanWrite(typeof(string), MediaType.ALL));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Read()
|
||||
{
|
||||
string body = "Hello Bruno Baïa";
|
||||
|
||||
HttpWebResponse webResponse = mocks.CreateMock<HttpWebResponse>();
|
||||
Expect.Call<Stream>(webResponse.GetResponseStream()).Return(new MemoryStream(Encoding.UTF8.GetBytes(body))).Repeat.Once();
|
||||
Expect.Call<string>(webResponse.CharacterSet).Return("utf-8").Repeat.Twice();
|
||||
|
||||
mocks.ReplayAll();
|
||||
|
||||
string result = converter.Read<string>(webResponse);
|
||||
Assert.AreEqual(body, result, "Invalid result");
|
||||
|
||||
mocks.VerifyAll();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WriteDefaultCharset()
|
||||
{
|
||||
string body = "H\u00e9llo W\u00f6rld";
|
||||
|
||||
string charSet = "ISO-8859-1";
|
||||
Encoding charSetEncoding = Encoding.GetEncoding(charSet);
|
||||
|
||||
HttpWebRequest webRequest = WebRequest.Create("http://localhost") as HttpWebRequest;
|
||||
webRequest.Method = "POST";
|
||||
|
||||
converter.Write(body, null, webRequest);
|
||||
|
||||
using (Stream postStream = webRequest.GetRequestStream())
|
||||
{
|
||||
//Assert.AreEqual(body.Length, postStream.Length, "Invalid result");
|
||||
}
|
||||
|
||||
Assert.AreEqual(new MediaType("text", "plain", charSet), MediaType.ParseMediaType(webRequest.ContentType), "Invalid content-type");
|
||||
Assert.AreEqual(charSetEncoding.GetBytes(body).Length, webRequest.ContentLength, "Invalid content-length");
|
||||
//Assert.IsFalse(String.IsNullOrEmpty(webRequest.Headers[HttpRequestHeader.AcceptCharset]), "Invalid accept-charset");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WriteUTF8()
|
||||
{
|
||||
string body = "H\u00e9llo W\u00f6rld";
|
||||
|
||||
string charSet = "UTF-8";
|
||||
Encoding charSetEncoding = Encoding.GetEncoding(charSet);
|
||||
MediaType mediaType = new MediaType("text", "plain", charSet);
|
||||
|
||||
HttpWebRequest webRequest = WebRequest.Create("http://localhost") as HttpWebRequest;
|
||||
webRequest.Method = "POST";
|
||||
|
||||
converter.Write(body, mediaType, webRequest);
|
||||
|
||||
using (Stream postStream = webRequest.GetRequestStream())
|
||||
{
|
||||
//Assert.AreEqual(body.Length, postStream.Length, "Invalid result");
|
||||
}
|
||||
|
||||
Assert.AreEqual(mediaType, MediaType.ParseMediaType(webRequest.ContentType), "Invalid content-type");
|
||||
Assert.AreEqual(charSetEncoding.GetBytes(body).Length, webRequest.ContentLength, "Invalid content-length");
|
||||
//Assert.IsFalse(String.IsNullOrEmpty(webRequest.Headers[HttpRequestHeader.AcceptCharset]), "Invalid accept-charset");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,328 @@
|
||||
#if NET_4_0
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Collections.Generic;
|
||||
using System.ServiceModel;
|
||||
using System.ServiceModel.Web;
|
||||
|
||||
using Spring.Http.Converters;
|
||||
using Spring.Http.Converters.Xml;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Spring.Http.Rest.Xml
|
||||
{
|
||||
/// <summary>
|
||||
/// Integration tests for the DataContractHttpMessageConverter class.
|
||||
/// </summary>
|
||||
/// <author>Bruno Baia</author>
|
||||
[TestFixture]
|
||||
public class DataContractHttpMessageConverterIntegrationTests
|
||||
{
|
||||
#region Logging
|
||||
|
||||
private static readonly Common.Logging.ILog LOG = Common.Logging.LogManager.GetLogger(typeof(RestTemplateIntegrationTests));
|
||||
|
||||
#endregion
|
||||
|
||||
private WebServiceHost webServiceHost;
|
||||
private string uri = "http://localhost:1337";
|
||||
private RestTemplate template;
|
||||
private MediaType contentType;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
template = new RestTemplate(uri);
|
||||
template.MessageConverters = new List<IHttpMessageConverter>();
|
||||
template.MessageConverters.Add(new StringHttpMessageConverter()); // for debugging purpose
|
||||
|
||||
contentType = new MediaType("application", "xml");
|
||||
|
||||
webServiceHost = new WebServiceHost(typeof(TestService), new Uri(uri));
|
||||
webServiceHost.Open();
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TearDownClass()
|
||||
{
|
||||
webServiceHost.Close();
|
||||
}
|
||||
|
||||
//[Test]
|
||||
//public void GetString()
|
||||
//{
|
||||
// string result = template.GetForObject<string>("users");
|
||||
// Assert.AreEqual("2", result, "Invalid content");
|
||||
//}
|
||||
|
||||
[Test]
|
||||
public void GetUser()
|
||||
{
|
||||
template.MessageConverters.Add(new DataContractHttpMessageConverter());
|
||||
|
||||
User result = template.GetForObject<User>("user/{id}", "1");
|
||||
Assert.IsNotNull(result, "Invalid content");
|
||||
Assert.AreEqual("1", result.ID, "Invalid content");
|
||||
Assert.AreEqual("Bruno Baïa", result.Name, "Invalid content");
|
||||
}
|
||||
|
||||
//[Test]
|
||||
//public void GetStringDictionaryTemplateVariables()
|
||||
//{
|
||||
// IDictionary<string, string> uriVariables = new Dictionary<string, string>(1);
|
||||
// uriVariables.Add("id", "2");
|
||||
// string result = template.GetForObject<string>("user/{id}", uriVariables);
|
||||
// Assert.AreEqual("Marie Baia", result, "Invalid content");
|
||||
//}
|
||||
|
||||
//[Test]
|
||||
//[ExpectedException(typeof(RestClientException),
|
||||
// ExpectedMessage = "The server returned 'User with id '5' not found' with the status code 404 - NotFound.")]
|
||||
//public void GetStringError()
|
||||
//{
|
||||
// string result = template.GetForObject<string>("user/{id}", "5");
|
||||
//}
|
||||
|
||||
//[Test]
|
||||
//public void GetStringForMessage()
|
||||
//{
|
||||
// HttpResponseMessage<string> result = template.GetForMessage<string>("user/{id}", "1");
|
||||
// Assert.AreEqual("Bruno Baïa", result.Body, "Invalid content");
|
||||
// Assert.AreEqual(contentType, MediaType.ParseMediaType(result.Headers[HttpResponseHeader.ContentType]), "Invalid content-type");
|
||||
// Assert.AreEqual(HttpStatusCode.OK, result.StatusCode, "Invalid status code");
|
||||
// Assert.AreEqual("OK", result.StatusDescription, "Invalid status description");
|
||||
//}
|
||||
|
||||
//[Test]
|
||||
//[ExpectedException(typeof(RestClientException),
|
||||
// ExpectedMessage = "Could not extract response: no Content-Type found")]
|
||||
//public void GetStringNoResponse()
|
||||
//{
|
||||
// string result = template.GetForObject<string>("/nothing");
|
||||
//}
|
||||
|
||||
//[Test]
|
||||
//public void HeadForHeaders()
|
||||
//{
|
||||
// WebHeaderCollection result = template.HeadForHeaders("head");
|
||||
// Assert.AreEqual(new MediaType("text", "plain"), MediaType.ParseMediaType(result[HttpResponseHeader.ContentType]), "Invalid content-type");
|
||||
//}
|
||||
|
||||
//[Test]
|
||||
//public void PostStringForLocation()
|
||||
//{
|
||||
// Uri result = template.PostForLocation("user", "Lisa Baia");
|
||||
// Assert.AreEqual(new Uri(new Uri(uri), "/user/3"), result, "Invalid location");
|
||||
//}
|
||||
|
||||
//[Test]
|
||||
//public void PostStringForMessage()
|
||||
//{
|
||||
// HttpResponseMessage<string> result = template.PostForMessage<string>("user", "Lisa Baia");
|
||||
// Assert.AreEqual(new Uri(new Uri(uri), "/user/3"), new Uri(result.Headers[HttpResponseHeader.Location]), "Invalid location");
|
||||
// Assert.AreEqual(HttpStatusCode.Created, result.StatusCode, "Invalid status code");
|
||||
// Assert.AreEqual("User id '3' created with 'Lisa Baia'", result.StatusDescription, "Invalid status description");
|
||||
// Assert.AreEqual("3", result.Body, "Invalid content");
|
||||
//}
|
||||
|
||||
[Test]
|
||||
public void PostStringForObject()
|
||||
{
|
||||
template.MessageConverters.Add(new DataContractHttpMessageConverter());
|
||||
|
||||
User user = new User() { Name = "Lisa Baia" };
|
||||
|
||||
User result = template.PostForObject<User>("user", user);
|
||||
Assert.AreEqual("3", result.ID, "Invalid content");
|
||||
Assert.AreEqual(user.Name, result.Name, "Invalid content");
|
||||
}
|
||||
|
||||
//[Test]
|
||||
//[ExpectedException(typeof(RestClientException),
|
||||
// ExpectedMessage = "The server returned 'Content cannot be null or empty' with the status code 400 - BadRequest.")]
|
||||
//public void PostStringForObjectWithError()
|
||||
//{
|
||||
// string result = template.PostForObject<string>("user", "");
|
||||
//}
|
||||
|
||||
//[Test]
|
||||
//public void Put()
|
||||
//{
|
||||
// string result = template.GetForObject<string>("user/1");
|
||||
// Assert.AreEqual("Bruno Baïa", result, "Invalid content");
|
||||
|
||||
// template.Put("user/1", "Bruno Baia");
|
||||
|
||||
// result = template.GetForObject<string>("user/1");
|
||||
// Assert.AreEqual("Bruno Baia", result, "Invalid content");
|
||||
//}
|
||||
|
||||
//[Test]
|
||||
//[ExpectedException(typeof(RestClientException),
|
||||
// ExpectedMessage = "The server returned 'User id '4' does not exist' with the status code 400 - BadRequest.")]
|
||||
//public void PutWithError()
|
||||
//{
|
||||
// template.Put("user/4", "Dinora Baia");
|
||||
//}
|
||||
|
||||
//[Test]
|
||||
//public void Delete()
|
||||
//{
|
||||
// string result = template.GetForObject<string>("users");
|
||||
// Assert.AreEqual("2", result, "Invalid content");
|
||||
|
||||
// template.Delete("user/2");
|
||||
|
||||
// result = template.GetForObject<string>("users");
|
||||
// Assert.AreEqual("1", result, "Invalid content");
|
||||
//}
|
||||
|
||||
//[Test]
|
||||
//[ExpectedException(typeof(RestClientException),
|
||||
// ExpectedMessage = "The server returned 'User id '10' does not exist' with the status code 400 - BadRequest.")]
|
||||
//public void DeleteWithError()
|
||||
//{
|
||||
// template.Delete("user/10");
|
||||
//}
|
||||
|
||||
//[Test]
|
||||
//public void OptionsForAllow()
|
||||
//{
|
||||
// IList<HttpMethod> result = template.OptionsForAllow("allow");
|
||||
// Assert.AreEqual(3, result.Count, "Invalid response");
|
||||
// Assert.IsTrue(result.Contains(HttpMethod.GET), "Invalid response");
|
||||
// Assert.IsTrue(result.Contains(HttpMethod.HEAD), "Invalid response");
|
||||
// Assert.IsTrue(result.Contains(HttpMethod.PUT), "Invalid response");
|
||||
//}
|
||||
|
||||
//[Test]
|
||||
//public void ExchangePost()
|
||||
//{
|
||||
// HttpResponseMessage<string> result = template.Exchange<string>(
|
||||
// "user", new HttpRequestMessage("Maryse Baia", HttpMethod.POST));
|
||||
|
||||
// Assert.AreEqual("3", result.Body, "Invalid content");
|
||||
// Assert.AreEqual(HttpStatusCode.Created, result.StatusCode, "Invalid status code");
|
||||
// Assert.AreEqual("User id '3' created with 'Maryse Baia'", result.StatusDescription, "Invalid status description");
|
||||
//}
|
||||
|
||||
//[Test]
|
||||
//public void ExchangePut()
|
||||
//{
|
||||
// HttpResponseMessage<string> result = template.Exchange<string>(
|
||||
// "user/1", new HttpRequestMessage("Bruno Baia", HttpMethod.PUT));
|
||||
|
||||
// Assert.AreEqual(HttpStatusCode.OK, result.StatusCode, "Invalid status code");
|
||||
// Assert.AreEqual("User id '1' updated with 'Bruno Baia'", result.StatusDescription, "Invalid status description");
|
||||
//}
|
||||
|
||||
//[Test]
|
||||
//[ExpectedException(ExpectedMessage = "The server returned 'Not Found' with the status code 404 - NotFound.")]
|
||||
//public void ClientError()
|
||||
//{
|
||||
// template.Execute<object>("clienterror", null, null);
|
||||
//}
|
||||
|
||||
//[Test]
|
||||
//[ExpectedException(ExpectedMessage = "The server returned 'Internal Server Error' with the status code 500 - InternalServerError.")]
|
||||
//public void ServerError()
|
||||
//{
|
||||
// template.Execute<object>("servererror", null, null);
|
||||
//}
|
||||
|
||||
#region REST test service
|
||||
|
||||
//[DataContract]
|
||||
public class User
|
||||
{
|
||||
//[DataMember]
|
||||
public string ID { get; set; }
|
||||
|
||||
//[DataMember]
|
||||
public string Name { get; set; }
|
||||
}
|
||||
|
||||
[ServiceContract]
|
||||
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
|
||||
public class TestService
|
||||
{
|
||||
private IList<User> users;
|
||||
|
||||
public TestService()
|
||||
{
|
||||
users = new List<User>();
|
||||
users.Add(new User() { ID = "1", Name = "Bruno Baïa" });
|
||||
users.Add(new User() { ID = "2", Name = "Marie Baia" });
|
||||
}
|
||||
|
||||
[WebGet(UriTemplate = "user/{id}")]
|
||||
public User GetUser(string id)
|
||||
{
|
||||
WebOperationContext context = WebOperationContext.Current;
|
||||
|
||||
foreach (User user in this.users)
|
||||
{
|
||||
if (user.ID.Equals(id, StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
return user;
|
||||
}
|
||||
}
|
||||
|
||||
context.OutgoingResponse.SetStatusAsNotFound(String.Format("User with id '{0}' not found", id));
|
||||
return null;
|
||||
}
|
||||
|
||||
[WebInvoke(UriTemplate = "user", Method = "POST")]
|
||||
public User Post(User user)
|
||||
{
|
||||
WebOperationContext context = WebOperationContext.Current;
|
||||
|
||||
UriTemplateMatch match = context.IncomingRequest.UriTemplateMatch;
|
||||
UriTemplate template = new UriTemplate("/user/{id}");
|
||||
|
||||
MediaType mediaType = MediaType.ParseMediaType(context.IncomingRequest.ContentType);
|
||||
|
||||
user.ID = (users.Count + 1).ToString(); // generate new ID
|
||||
|
||||
if (!String.IsNullOrEmpty(user.ID))
|
||||
{
|
||||
context.OutgoingResponse.StatusCode = HttpStatusCode.BadRequest;
|
||||
context.OutgoingResponse.StatusDescription = "Content cannot be null or empty";
|
||||
return user;
|
||||
}
|
||||
|
||||
users.Add(user);
|
||||
|
||||
Uri uri = template.BindByPosition(match.BaseUri, user.ID);
|
||||
context.OutgoingResponse.SetStatusAsCreated(uri);
|
||||
context.OutgoingResponse.StatusDescription = String.Format("User id '{0}' created", user.ID);
|
||||
|
||||
return user;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,119 @@
|
||||
#if NET_3_0
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
|
||||
using NUnit.Framework;
|
||||
using Rhino.Mocks;
|
||||
using System.Xml;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Spring.Http.Converters.Xml
|
||||
{
|
||||
/// <summary>
|
||||
/// Unit tests for the DataContractHttpMessageConverter class.
|
||||
/// </summary>
|
||||
/// <author>Bruno Baia</author>
|
||||
[TestFixture]
|
||||
public class DataContractHttpMessageConverterTests
|
||||
{
|
||||
private DataContractHttpMessageConverter converter;
|
||||
private MockRepository mocks;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
mocks = new MockRepository();
|
||||
converter = new DataContractHttpMessageConverter();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanRead()
|
||||
{
|
||||
Assert.IsTrue(converter.CanRead(typeof(CustomClass), new MediaType("application", "xml")));
|
||||
Assert.IsTrue(converter.CanRead(typeof(CustomClass), new MediaType("text", "xml")));
|
||||
Assert.IsTrue(converter.CanRead(typeof(CustomClass), new MediaType("application", "soap+xml"))); // application/*+xml
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanWrite()
|
||||
{
|
||||
Assert.IsTrue(converter.CanWrite(typeof(CustomClass), new MediaType("application", "xml")));
|
||||
Assert.IsTrue(converter.CanWrite(typeof(CustomClass), new MediaType("text", "xml")));
|
||||
Assert.IsTrue(converter.CanRead(typeof(CustomClass), new MediaType("application", "soap+xml"))); // application/*+xml
|
||||
}
|
||||
|
||||
//[Test]
|
||||
//public void Read()
|
||||
//{
|
||||
// string body = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?><TestElement testAttribute=\"value\" />";
|
||||
|
||||
// HttpWebResponse webResponse = mocks.CreateMock<HttpWebResponse>();
|
||||
// Expect.Call<Stream>(webResponse.GetResponseStream()).Return(new MemoryStream(Encoding.UTF8.GetBytes(body))).Repeat.Once();
|
||||
|
||||
// mocks.ReplayAll();
|
||||
|
||||
// XmlDocument result = converter.Read<XmlDocument>(webResponse);
|
||||
// Assert.IsNotNull(result, "Invalid result");
|
||||
|
||||
// mocks.VerifyAll();
|
||||
//}
|
||||
|
||||
//[Test]
|
||||
//public void Write()
|
||||
//{
|
||||
// XmlDocument body = new XmlDocument();
|
||||
// body.CreateElement("TestElement");
|
||||
|
||||
// HttpWebRequest webRequest = WebRequest.Create("http://localhost") as HttpWebRequest;
|
||||
// webRequest.Method = "POST";
|
||||
|
||||
// converter.Write(body, null, webRequest);
|
||||
|
||||
// Assert.AreEqual(new MediaType("application", "xml"), MediaType.ParseMediaType(webRequest.ContentType), "Invalid content-type");
|
||||
|
||||
// using (Stream postStream = webRequest.GetRequestStream())
|
||||
// {
|
||||
// using (StreamReader reader = new StreamReader(postStream))
|
||||
// {
|
||||
// string result = reader.ReadToEnd();
|
||||
// Assert.AreEqual(result.Length, webRequest.ContentLength, "Invalid content-length");
|
||||
// }
|
||||
|
||||
// }
|
||||
//}
|
||||
|
||||
#region Test classes
|
||||
|
||||
[DataContract]
|
||||
public class CustomClass
|
||||
{
|
||||
[DataMember]
|
||||
public string ID { get; set; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,105 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
|
||||
using NUnit.Framework;
|
||||
using Rhino.Mocks;
|
||||
using System.Xml;
|
||||
|
||||
namespace Spring.Http.Converters.Xml
|
||||
{
|
||||
/// <summary>
|
||||
/// Unit tests for the XmlDocumentHttpMessageConverter class.
|
||||
/// </summary>
|
||||
/// <author>Bruno Baia</author>
|
||||
[TestFixture]
|
||||
public class XmlDocumentHttpMessageConverterTests
|
||||
{
|
||||
private XmlDocumentHttpMessageConverter converter;
|
||||
private MockRepository mocks;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
mocks = new MockRepository();
|
||||
converter = new XmlDocumentHttpMessageConverter();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanRead()
|
||||
{
|
||||
Assert.IsTrue(converter.CanRead(typeof(XmlDocument), new MediaType("application", "xml")));
|
||||
Assert.IsTrue(converter.CanRead(typeof(XmlDocument), new MediaType("text", "xml")));
|
||||
Assert.IsTrue(converter.CanRead(typeof(XmlDocument), new MediaType("application", "soap+xml"))); // application/*+xml
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanWrite()
|
||||
{
|
||||
Assert.IsTrue(converter.CanWrite(typeof(XmlDocument), new MediaType("application", "xml")));
|
||||
Assert.IsTrue(converter.CanWrite(typeof(XmlDocument), new MediaType("text", "xml")));
|
||||
Assert.IsTrue(converter.CanRead(typeof(XmlDocument), new MediaType("application", "soap+xml"))); // application/*+xml
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Read()
|
||||
{
|
||||
string body = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?><TestElement testAttribute=\"value\" />";
|
||||
|
||||
HttpWebResponse webResponse = mocks.CreateMock<HttpWebResponse>();
|
||||
Expect.Call<Stream>(webResponse.GetResponseStream()).Return(new MemoryStream(Encoding.UTF8.GetBytes(body))).Repeat.Once();
|
||||
|
||||
mocks.ReplayAll();
|
||||
|
||||
XmlDocument result = converter.Read<XmlDocument>(webResponse);
|
||||
Assert.IsNotNull(result, "Invalid result");
|
||||
|
||||
mocks.VerifyAll();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Write()
|
||||
{
|
||||
XmlDocument body = new XmlDocument();
|
||||
body.CreateElement("TestElement");
|
||||
|
||||
HttpWebRequest webRequest = WebRequest.Create("http://localhost") as HttpWebRequest;
|
||||
webRequest.Method = "POST";
|
||||
|
||||
converter.Write(body, null, webRequest);
|
||||
|
||||
Assert.AreEqual(new MediaType("application", "xml"), MediaType.ParseMediaType(webRequest.ContentType), "Invalid content-type");
|
||||
|
||||
using (Stream postStream = webRequest.GetRequestStream())
|
||||
{
|
||||
using (StreamReader reader = new StreamReader(postStream))
|
||||
{
|
||||
string result = reader.ReadToEnd();
|
||||
Assert.AreEqual(result.Length, webRequest.ContentLength, "Invalid content-length");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
544
test/Spring/Spring.Http.Tests/Http/MediaTypeTests.cs
Normal file
544
test/Spring/Spring.Http.Tests/Http/MediaTypeTests.cs
Normal file
@@ -0,0 +1,544 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Spring.Http
|
||||
{
|
||||
/// <summary>
|
||||
/// Unit tests for the MediaType class.
|
||||
/// </summary>
|
||||
/// <author>Arjen Poutsma</author>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <author>Bruno Baia (.NET)</author>
|
||||
[TestFixture]
|
||||
public class MediaTypeTests
|
||||
{
|
||||
[Test]
|
||||
public void Includes()
|
||||
{
|
||||
MediaType textPlain = MediaType.TEXT_PLAIN;
|
||||
Assert.IsTrue(textPlain.Includes(textPlain), "Equal types is not inclusive");
|
||||
MediaType allText = new MediaType("text");
|
||||
|
||||
Assert.IsTrue(allText.Includes(textPlain), "All subtypes is not inclusive");
|
||||
Assert.IsFalse(textPlain.Includes(allText), "All subtypes is inclusive");
|
||||
|
||||
Assert.IsTrue(MediaType.ALL.Includes(textPlain), "All types is not inclusive");
|
||||
Assert.IsFalse(textPlain.Includes(MediaType.ALL), "All types is inclusive");
|
||||
|
||||
Assert.IsTrue(MediaType.ALL.Includes(textPlain), "All types is not inclusive");
|
||||
Assert.IsFalse(textPlain.Includes(MediaType.ALL), "All types is inclusive");
|
||||
|
||||
MediaType applicationSoapXml = new MediaType("application", "soap+xml");
|
||||
MediaType applicationWildcardXml = new MediaType("application", "*+xml");
|
||||
|
||||
Assert.IsTrue(applicationSoapXml.Includes(applicationSoapXml));
|
||||
Assert.IsTrue(applicationWildcardXml.Includes(applicationWildcardXml));
|
||||
|
||||
Assert.IsTrue(applicationWildcardXml.Includes(applicationSoapXml));
|
||||
Assert.IsFalse(applicationSoapXml.Includes(applicationWildcardXml));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IsCompatible()
|
||||
{
|
||||
MediaType textPlain = MediaType.TEXT_PLAIN;
|
||||
Assert.IsTrue(textPlain.IsCompatibleWith(textPlain), "Equal types is not compatible");
|
||||
MediaType allText = new MediaType("text");
|
||||
|
||||
Assert.IsTrue(allText.IsCompatibleWith(textPlain), "All subtypes is not compatible");
|
||||
Assert.IsTrue(textPlain.IsCompatibleWith(allText), "All subtypes is not compatible");
|
||||
|
||||
Assert.IsTrue(MediaType.ALL.IsCompatibleWith(textPlain), "All types is not compatible");
|
||||
Assert.IsTrue(textPlain.IsCompatibleWith(MediaType.ALL), "All types is not compatible");
|
||||
|
||||
Assert.IsTrue(MediaType.ALL.IsCompatibleWith(textPlain), "All types is not compatible");
|
||||
Assert.IsTrue(textPlain.IsCompatibleWith(MediaType.ALL), "All types is compatible");
|
||||
|
||||
MediaType applicationSoapXml = new MediaType("application", "soap+xml");
|
||||
MediaType applicationWildcardXml = new MediaType("application", "*+xml");
|
||||
|
||||
Assert.IsTrue(applicationSoapXml.IsCompatibleWith(applicationSoapXml));
|
||||
Assert.IsTrue(applicationWildcardXml.IsCompatibleWith(applicationWildcardXml));
|
||||
|
||||
Assert.IsTrue(applicationWildcardXml.IsCompatibleWith(applicationSoapXml));
|
||||
Assert.IsTrue(applicationSoapXml.IsCompatibleWith(applicationWildcardXml));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestToString()
|
||||
{
|
||||
MediaType mediaType = new MediaType("text", "plain", 0.7);
|
||||
String result = mediaType.ToString();
|
||||
Assert.AreEqual("text/plain;q=0.7", result, "Invalid toString() returned");
|
||||
}
|
||||
|
||||
//[Test](expected= IllegalArgumentException.class)
|
||||
//public void slashInType() {
|
||||
// new MediaType("text/plain");
|
||||
//}
|
||||
|
||||
//[Test](expected= IllegalArgumentException.class)
|
||||
//public void slashInSubtype() {
|
||||
// new MediaType("text", "/");
|
||||
//}
|
||||
|
||||
[Test]
|
||||
public void GetDefaultQualityValue()
|
||||
{
|
||||
MediaType mediaType = new MediaType("text", "plain");
|
||||
Assert.AreEqual(1, mediaType.QualityValue, "Invalid quality value");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ParseMediaType()
|
||||
{
|
||||
string s = "audio/*; q=0.2";
|
||||
MediaType mediaType = MediaType.ParseMediaType(s);
|
||||
Assert.AreEqual("audio", mediaType.Type, "Invalid type");
|
||||
Assert.AreEqual("*", mediaType.Subtype, "Invalid subtype");
|
||||
Assert.AreEqual(0.2, mediaType.QualityValue, "Invalid quality factor");
|
||||
}
|
||||
|
||||
[Test]
|
||||
[ExpectedException(typeof(ArgumentException))]
|
||||
public void ParseMediaTypeNoSubtype()
|
||||
{
|
||||
MediaType.ParseMediaType("audio");
|
||||
}
|
||||
|
||||
[Test]
|
||||
[ExpectedException(typeof(ArgumentException))]
|
||||
public void ParseMediaTypeNoSubtypeSlash()
|
||||
{
|
||||
MediaType.ParseMediaType("audio/");
|
||||
}
|
||||
|
||||
//[Test](expected = IllegalArgumentException.class)
|
||||
//public void parseMediaTypeIllegalType() {
|
||||
// MediaType.parseMediaType("audio(/basic");
|
||||
//}
|
||||
|
||||
//[Test](expected = IllegalArgumentException.class)
|
||||
//public void parseMediaTypeIllegalSubtype() {
|
||||
// MediaType.parseMediaType("audio/basic)");
|
||||
//}
|
||||
|
||||
//[Test](expected = IllegalArgumentException.class)
|
||||
//public void parseMediaTypeEmptyParameterAttribute() {
|
||||
// MediaType.parseMediaType("audio/*;=value");
|
||||
//}
|
||||
|
||||
//[Test](expected = IllegalArgumentException.class)
|
||||
//public void parseMediaTypeEmptyParameterValue() {
|
||||
// MediaType.parseMediaType("audio/*;attr=");
|
||||
//}
|
||||
|
||||
//[Test](expected = IllegalArgumentException.class)
|
||||
//public void parseMediaTypeIllegalParameterAttribute() {
|
||||
// MediaType.parseMediaType("audio/*;attr<=value");
|
||||
//}
|
||||
|
||||
//[Test](expected = IllegalArgumentException.class)
|
||||
//public void parseMediaTypeIllegalParameterValue() {
|
||||
// MediaType.parseMediaType("audio/*;attr=v>alue");
|
||||
//}
|
||||
|
||||
//[Test](expected = IllegalArgumentException.class)
|
||||
//public void parseMediaTypeIllegalQualityFactor() {
|
||||
// MediaType.parseMediaType("audio/basic;q=1.1");
|
||||
//}
|
||||
|
||||
//[Test](expected = IllegalArgumentException.class)
|
||||
//public void parseMediaTypeIllegalCharset() {
|
||||
// MediaType.parseMediaType("text/html; charset=foo-bar");
|
||||
//}
|
||||
|
||||
//[Test]
|
||||
//public void parseMediaTypeQuotedParameterValue() {
|
||||
// MediaType.parseMediaType("audio/*;attr=\"v>alue\"");
|
||||
//}
|
||||
|
||||
//[Test](expected = IllegalArgumentException.class)
|
||||
//public void parseMediaTypeIllegalQuotedParameterValue() {
|
||||
// MediaType.parseMediaType("audio/*;attr=\"");
|
||||
//}
|
||||
|
||||
//[Test]
|
||||
//public void parseCharset() throws Exception {
|
||||
// String s = "text/html; charset=iso-8859-1";
|
||||
// MediaType mediaType = MediaType.parseMediaType(s);
|
||||
// Assert.AreEqual("Invalid type", "text", mediaType.getType());
|
||||
// Assert.AreEqual("Invalid subtype", "html", mediaType.getSubtype());
|
||||
// Assert.AreEqual("Invalid charset", Charset.forName("ISO-8859-1"), mediaType.getCharSet());
|
||||
//}
|
||||
|
||||
//[Test]
|
||||
//public void parseQuotedCharset() {
|
||||
// String s = "application/xml;charset=\"utf-8\"";
|
||||
// MediaType mediaType = MediaType.parseMediaType(s);
|
||||
// Assert.AreEqual("Invalid type", "application", mediaType.getType());
|
||||
// Assert.AreEqual("Invalid subtype", "xml", mediaType.getSubtype());
|
||||
// Assert.AreEqual("Invalid charset", Charset.forName("UTF-8"), mediaType.getCharSet());
|
||||
//}
|
||||
|
||||
[Test]
|
||||
public void ParseURLConnectionMediaType()
|
||||
{
|
||||
string s = "*; q=.2";
|
||||
MediaType mediaType = MediaType.ParseMediaType(s);
|
||||
Assert.AreEqual(mediaType.Type, "*", "Invalid type");
|
||||
Assert.AreEqual("*", mediaType.Subtype, "Invalid subtype");
|
||||
Assert.AreEqual(0.2, mediaType.QualityValue, "Invalid quality factor");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ParseMediaTypes()
|
||||
{
|
||||
string s = "text/plain; q=0.5, text/html, text/x-dvi; q=0.8, text/x-c";
|
||||
List<MediaType> mediaTypes = MediaType.ParseMediaTypes(s);
|
||||
Assert.NotNull(mediaTypes, "No media types returned");
|
||||
Assert.AreEqual(4, mediaTypes.Count, "Invalid amount of media types");
|
||||
|
||||
mediaTypes = MediaType.ParseMediaTypes(null);
|
||||
Assert.NotNull(mediaTypes, "No media types returned");
|
||||
Assert.AreEqual(0, mediaTypes.Count, "Invalid amount of media types");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CompareTo()
|
||||
{
|
||||
MediaType audioBasic = new MediaType("audio", "basic");
|
||||
MediaType audio = new MediaType("audio");
|
||||
MediaType audioWave = new MediaType("audio", "wave");
|
||||
MediaType audioBasicLevel = new MediaType("audio", "basic", SingletonDictionary<string, string>("level", "1"));
|
||||
MediaType audioBasic07 = new MediaType("audio", "basic", 0.7);
|
||||
|
||||
// equal
|
||||
Assert.AreEqual(0, audioBasic.CompareTo(audioBasic), "Invalid comparison result");
|
||||
Assert.AreEqual(0, audio.CompareTo(audio), "Invalid comparison result");
|
||||
Assert.AreEqual(0, audioBasicLevel.CompareTo(audioBasicLevel), "Invalid comparison result");
|
||||
|
||||
Assert.IsTrue(audioBasicLevel.CompareTo(audio) > 0, "Invalid comparison result");
|
||||
|
||||
List<MediaType> expected = new List<MediaType>();
|
||||
expected.Add(audio);
|
||||
expected.Add(audioBasic);
|
||||
expected.Add(audioBasicLevel);
|
||||
expected.Add(audioBasic07);
|
||||
expected.Add(audioWave);
|
||||
|
||||
List<MediaType> result = new List<MediaType>(expected);
|
||||
// shuffle & sort 10 times
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
result.Sort(ShuffleComparison);
|
||||
result.Sort();
|
||||
|
||||
for (int j = 0; j < result.Count; j++)
|
||||
{
|
||||
Assert.AreSame(expected[j], result[j], "Invalid media type at " + j + ", run " + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CompareToConsistentWithEquals()
|
||||
{
|
||||
MediaType m1 = MediaType.ParseMediaType("text/html; q=0.7; charset=iso-8859-1");
|
||||
MediaType m2 = MediaType.ParseMediaType("text/html; charset=iso-8859-1; q=0.7");
|
||||
|
||||
Assert.AreEqual(m1, m2, "Media types not equal");
|
||||
Assert.AreEqual(0, m1.CompareTo(m2), "compareTo() not consistent with equals");
|
||||
Assert.AreEqual(0, m2.CompareTo(m1), "compareTo() not consistent with equals");
|
||||
|
||||
m1 = MediaType.ParseMediaType("text/html; q=0.7; charset=iso-8859-1");
|
||||
m2 = MediaType.ParseMediaType("text/html; Q=0.7; charset=iso-8859-1");
|
||||
Assert.AreEqual(m1, m2, "Media types not equal");
|
||||
Assert.AreEqual(0, m1.CompareTo(m2), "compareTo() not consistent with equals");
|
||||
Assert.AreEqual(0, m2.CompareTo(m1), "compareTo() not consistent with equals");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CompareToCaseSensitivity()
|
||||
{
|
||||
MediaType m1 = new MediaType("audio", "basic");
|
||||
MediaType m2 = new MediaType("Audio", "Basic");
|
||||
Assert.AreEqual(0, m1.CompareTo(m2), "Invalid comparison result");
|
||||
Assert.AreEqual(0, m2.CompareTo(m1), "Invalid comparison result");
|
||||
|
||||
m1 = new MediaType("audio", "basic", SingletonDictionary<string, string>("foo", "bar"));
|
||||
m2 = new MediaType("audio", "basic", SingletonDictionary<string, string>("Foo", "bar"));
|
||||
Assert.AreEqual(0, m1.CompareTo(m2), "Invalid comparison result");
|
||||
Assert.AreEqual(0, m2.CompareTo(m1), "Invalid comparison result");
|
||||
|
||||
m1 = new MediaType("audio", "basic", SingletonDictionary<string, string>("foo", "bar"));
|
||||
m2 = new MediaType("audio", "basic", SingletonDictionary<string, string>("foo", "Bar"));
|
||||
Assert.IsTrue(m1.CompareTo(m2) != 0, "Invalid comparison result");
|
||||
Assert.IsTrue(m2.CompareTo(m1) != 0, "Invalid comparison result");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SpecificityComparator()
|
||||
{
|
||||
MediaType audioBasic = new MediaType("audio", "basic");
|
||||
MediaType audioWave = new MediaType("audio", "wave");
|
||||
MediaType audio = new MediaType("audio");
|
||||
MediaType audio03 = new MediaType("audio", "*", 0.3);
|
||||
MediaType audio07 = new MediaType("audio", "*", 0.7);
|
||||
MediaType audioBasicLevel = new MediaType("audio", "basic", SingletonDictionary<string, string>("level", "1"));
|
||||
MediaType textHtml = new MediaType("text", "html");
|
||||
MediaType all = MediaType.ALL;
|
||||
|
||||
IComparer<MediaType> comp = MediaType.SPECIFICITY_COMPARER;
|
||||
|
||||
// equal
|
||||
Assert.AreEqual(0, comp.Compare(audioBasic,audioBasic), "Invalid comparison result");
|
||||
Assert.AreEqual(0, comp.Compare(audio, audio), "Invalid comparison result");
|
||||
Assert.AreEqual(0, comp.Compare(audio07, audio07), "Invalid comparison result");
|
||||
Assert.AreEqual(0, comp.Compare(audio03, audio03), "Invalid comparison result");
|
||||
Assert.AreEqual(0, comp.Compare(audioBasicLevel, audioBasicLevel), "Invalid comparison result");
|
||||
|
||||
// specific to unspecific
|
||||
Assert.IsTrue(comp.Compare(audioBasic, audio) < 0, "Invalid comparison result");
|
||||
Assert.IsTrue(comp.Compare(audioBasic, all) < 0, "Invalid comparison result");
|
||||
Assert.IsTrue(comp.Compare(audio, all) < 0, "Invalid comparison result");
|
||||
|
||||
// unspecific to specific
|
||||
Assert.IsTrue(comp.Compare(audio, audioBasic) > 0, "Invalid comparison result");
|
||||
Assert.IsTrue(comp.Compare(all, audioBasic) > 0, "Invalid comparison result");
|
||||
Assert.IsTrue(comp.Compare(all, audio) > 0, "Invalid comparison result");
|
||||
|
||||
// qualifiers
|
||||
Assert.IsTrue(comp.Compare(audio, audio07) < 0, "Invalid comparison result");
|
||||
Assert.IsTrue(comp.Compare(audio07, audio) > 0, "Invalid comparison result");
|
||||
Assert.IsTrue(comp.Compare(audio07, audio03) < 0, "Invalid comparison result");
|
||||
Assert.IsTrue(comp.Compare(audio03, audio07) > 0, "Invalid comparison result");
|
||||
Assert.IsTrue(comp.Compare(audio03, all) < 0, "Invalid comparison result");
|
||||
Assert.IsTrue(comp.Compare(all, audio03) > 0, "Invalid comparison result");
|
||||
|
||||
// other parameters
|
||||
Assert.IsTrue(comp.Compare(audioBasic, audioBasicLevel) > 0, "Invalid comparison result");
|
||||
Assert.IsTrue(comp.Compare(audioBasicLevel, audioBasic) < 0, "Invalid comparison result");
|
||||
|
||||
// different types
|
||||
Assert.AreEqual(0, comp.Compare(audioBasic, textHtml), "Invalid comparison result");
|
||||
Assert.AreEqual(0, comp.Compare(textHtml, audioBasic), "Invalid comparison result");
|
||||
|
||||
// different subtypes
|
||||
Assert.AreEqual(0, comp.Compare(audioBasic, audioWave), "Invalid comparison result");
|
||||
Assert.AreEqual(0, comp.Compare(audioWave, audioBasic), "Invalid comparison result");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SortBySpecificityRelated()
|
||||
{
|
||||
MediaType audioBasic = new MediaType("audio", "basic");
|
||||
MediaType audio = new MediaType("audio");
|
||||
MediaType audio03 = new MediaType("audio", "*", 0.3);
|
||||
MediaType audio07 = new MediaType("audio", "*", 0.7);
|
||||
MediaType audioBasicLevel = new MediaType("audio", "basic", SingletonDictionary<string, string>("level", "1"));
|
||||
MediaType all = MediaType.ALL;
|
||||
|
||||
List<MediaType> expected = new List<MediaType>();
|
||||
expected.Add(audioBasicLevel);
|
||||
expected.Add(audioBasic);
|
||||
expected.Add(audio);
|
||||
expected.Add(audio07);
|
||||
expected.Add(audio03);
|
||||
expected.Add(all);
|
||||
|
||||
List<MediaType> result = new List<MediaType>(expected);
|
||||
// shuffle & sort 10 times
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
result.Sort(ShuffleComparison);
|
||||
MediaType.SortBySpecificity(result);
|
||||
|
||||
for (int j = 0; j < result.Count; j++)
|
||||
{
|
||||
Assert.AreSame(expected[j], result[j], "Invalid media type at " + j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Ignore]
|
||||
public void SortBySpecificityUnrelated()
|
||||
{
|
||||
MediaType audioBasic = new MediaType("audio", "basic");
|
||||
MediaType audioWave = new MediaType("audio", "wave");
|
||||
MediaType textHtml = new MediaType("text", "html");
|
||||
|
||||
List<MediaType> expected = new List<MediaType>();
|
||||
expected.Add(textHtml);
|
||||
expected.Add(audioBasic);
|
||||
expected.Add(audioWave);
|
||||
|
||||
List<MediaType> result = new List<MediaType>(expected);
|
||||
MediaType.SortBySpecificity(result);
|
||||
|
||||
for (int i = 0; i < result.Count; i++)
|
||||
{
|
||||
Assert.AreSame(expected[i], result[i], "Invalid media type at " + i);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void QualityComparator()
|
||||
{
|
||||
MediaType audioBasic = new MediaType("audio", "basic");
|
||||
MediaType audioWave = new MediaType("audio", "wave");
|
||||
MediaType audio = new MediaType("audio");
|
||||
MediaType audio03 = new MediaType("audio", "*", 0.3);
|
||||
MediaType audio07 = new MediaType("audio", "*", 0.7);
|
||||
MediaType audioBasicLevel = new MediaType("audio", "basic", SingletonDictionary<string, string>("level", "1"));
|
||||
MediaType textHtml = new MediaType("text", "html");
|
||||
MediaType all = MediaType.ALL;
|
||||
|
||||
IComparer<MediaType> comp = MediaType.QUALITY_VALUE_COMPARER;
|
||||
|
||||
// equal
|
||||
Assert.AreEqual(0, comp.Compare(audioBasic, audioBasic), "Invalid comparison result");
|
||||
Assert.AreEqual(0, comp.Compare(audio, audio), "Invalid comparison result");
|
||||
Assert.AreEqual(0, comp.Compare(audio07, audio07), "Invalid comparison result");
|
||||
Assert.AreEqual(0, comp.Compare(audio03, audio03), "Invalid comparison result");
|
||||
Assert.AreEqual(0, comp.Compare(audioBasicLevel, audioBasicLevel), "Invalid comparison result");
|
||||
|
||||
// specific to unspecific
|
||||
Assert.IsTrue(comp.Compare(audioBasic, audio) < 0, "Invalid comparison result");
|
||||
Assert.IsTrue(comp.Compare(audioBasic, all) < 0, "Invalid comparison result");
|
||||
Assert.IsTrue(comp.Compare(audio, all) < 0, "Invalid comparison result");
|
||||
|
||||
// unspecific to specific
|
||||
Assert.IsTrue(comp.Compare(audio, audioBasic) > 0, "Invalid comparison result");
|
||||
Assert.IsTrue(comp.Compare(all, audioBasic) > 0, "Invalid comparison result");
|
||||
Assert.IsTrue(comp.Compare(all, audio) > 0, "Invalid comparison result");
|
||||
|
||||
// qualifiers
|
||||
Assert.IsTrue(comp.Compare(audio, audio07) < 0, "Invalid comparison result");
|
||||
Assert.IsTrue(comp.Compare(audio07, audio) > 0, "Invalid comparison result");
|
||||
Assert.IsTrue(comp.Compare(audio07, audio03) < 0, "Invalid comparison result");
|
||||
Assert.IsTrue(comp.Compare(audio03, audio07) > 0, "Invalid comparison result");
|
||||
Assert.IsTrue(comp.Compare(audio03, all) > 0, "Invalid comparison result");
|
||||
Assert.IsTrue(comp.Compare(all, audio03) < 0, "Invalid comparison result");
|
||||
|
||||
// other parameters
|
||||
Assert.IsTrue(comp.Compare(audioBasic, audioBasicLevel) > 0, "Invalid comparison result");
|
||||
Assert.IsTrue(comp.Compare(audioBasicLevel, audioBasic) < 0, "Invalid comparison result");
|
||||
|
||||
// different types
|
||||
Assert.AreEqual(0, comp.Compare(audioBasic, textHtml), "Invalid comparison result");
|
||||
Assert.AreEqual(0, comp.Compare(textHtml, audioBasic), "Invalid comparison result");
|
||||
|
||||
// different subtypes
|
||||
Assert.AreEqual(0, comp.Compare(audioBasic, audioWave), "Invalid comparison result");
|
||||
Assert.AreEqual(0, comp.Compare(audioWave, audioBasic), "Invalid comparison result");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SortByQualityRelated()
|
||||
{
|
||||
MediaType audioBasic = new MediaType("audio", "basic");
|
||||
MediaType audio = new MediaType("audio");
|
||||
MediaType audio03 = new MediaType("audio", "*", 0.3);
|
||||
MediaType audio07 = new MediaType("audio", "*", 0.7);
|
||||
MediaType audioBasicLevel = new MediaType("audio", "basic", SingletonDictionary<string, string>("level", "1"));
|
||||
MediaType all = MediaType.ALL;
|
||||
|
||||
List<MediaType> expected = new List<MediaType>();
|
||||
expected.Add(audioBasicLevel);
|
||||
expected.Add(audioBasic);
|
||||
expected.Add(audio);
|
||||
expected.Add(all);
|
||||
expected.Add(audio07);
|
||||
expected.Add(audio03);
|
||||
|
||||
List<MediaType> result = new List<MediaType>(expected);
|
||||
// shuffle & sort 10 times
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
result.Sort(ShuffleComparison);
|
||||
MediaType.SortByQualityValue(result);
|
||||
|
||||
for (int j = 0; j < result.Count; j++)
|
||||
{
|
||||
Assert.AreSame(expected[j], result[j], "Invalid media type at " + j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Ignore]
|
||||
public void SortByQualityUnrelated()
|
||||
{
|
||||
MediaType audioBasic = new MediaType("audio", "basic");
|
||||
MediaType audioWave = new MediaType("audio", "wave");
|
||||
MediaType textHtml = new MediaType("text", "html");
|
||||
|
||||
List<MediaType> expected = new List<MediaType>();
|
||||
expected.Add(textHtml);
|
||||
expected.Add(audioBasic);
|
||||
expected.Add(audioWave);
|
||||
|
||||
List<MediaType> result = new List<MediaType>(expected);
|
||||
MediaType.SortBySpecificity(result);
|
||||
|
||||
for (int i = 0; i < result.Count; i++)
|
||||
{
|
||||
Assert.AreSame(expected[i], result[i], "Invalid media type at " + i);
|
||||
}
|
||||
}
|
||||
|
||||
//[Test]
|
||||
//public void testWithConversionService() {
|
||||
// ConversionService conversionService = ConversionServiceFactory.createDefaultConversionService();
|
||||
// Assert.IsTrue(conversionService.canConvert(String.class, MediaType.class));
|
||||
// MediaType mediaType = MediaType.parseMediaType("application/xml");
|
||||
// Assert.AreEqual(mediaType, conversionService.convert("application/xml", MediaType.class));
|
||||
//}
|
||||
|
||||
#region Utils
|
||||
|
||||
private static int ShuffleComparison(MediaType mediaType1, MediaType mediaType2)
|
||||
{
|
||||
if (mediaType1 == mediaType2)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
Random rd = new Random();
|
||||
return rd.Next(-1, 2);
|
||||
}
|
||||
|
||||
private static IDictionary<TKey, TValue> SingletonDictionary<TKey, TValue>(TKey key, TValue value)
|
||||
{
|
||||
IDictionary<TKey, TValue> dictionary = new Dictionary<TKey, TValue>(1);
|
||||
dictionary.Add(key, value);
|
||||
return dictionary;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,486 @@
|
||||
#if NET_4_0
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Collections.Generic;
|
||||
using System.ServiceModel;
|
||||
using System.ServiceModel.Web;
|
||||
using System.ServiceModel.Channels;
|
||||
|
||||
using Spring.Http;
|
||||
using Spring.Http.Rest.Support;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Spring.Http.Rest
|
||||
{
|
||||
/// <summary>
|
||||
/// Integration tests for the RestTemplate class.
|
||||
/// </summary>
|
||||
/// <author>Arjen Poutsma</author>
|
||||
/// <author>Bruno Baia (.NET)</author>
|
||||
[TestFixture]
|
||||
public class RestTemplateIntegrationTests
|
||||
{
|
||||
#region Logging
|
||||
|
||||
private static readonly Common.Logging.ILog LOG = Common.Logging.LogManager.GetLogger(typeof(RestTemplateIntegrationTests));
|
||||
|
||||
#endregion
|
||||
|
||||
private WebServiceHost webServiceHost;
|
||||
private string uri = "http://localhost:1337";
|
||||
private RestTemplate template;
|
||||
private MediaType contentType;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
template = new RestTemplate(uri);
|
||||
contentType = new MediaType("text", "plain");
|
||||
|
||||
webServiceHost = new WebServiceHost(typeof(TestService), new Uri(uri));
|
||||
webServiceHost.Open();
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TearDownClass()
|
||||
{
|
||||
webServiceHost.Close();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetString()
|
||||
{
|
||||
string result = template.GetForObject<string>("users");
|
||||
Assert.AreEqual("2", result, "Invalid content");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetStringVarArgsTemplateVariables()
|
||||
{
|
||||
string result = template.GetForObject<string>("user/{id}", "1");
|
||||
Assert.AreEqual("Bruno Baïa", result, "Invalid content");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetStringDictionaryTemplateVariables()
|
||||
{
|
||||
IDictionary<string, string> uriVariables = new Dictionary<string, string>(1);
|
||||
uriVariables.Add("id", "2");
|
||||
string result = template.GetForObject<string>("user/{id}", uriVariables);
|
||||
Assert.AreEqual("Marie Baia", result, "Invalid content");
|
||||
}
|
||||
|
||||
[Test]
|
||||
[ExpectedException(typeof(RestClientException),
|
||||
ExpectedMessage = "The server returned 'User with id '5' not found' with the status code 404 - NotFound.")]
|
||||
public void GetStringError()
|
||||
{
|
||||
string result = template.GetForObject<string>("user/{id}", "5");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetStringForMessage()
|
||||
{
|
||||
HttpResponseMessage<string> result = template.GetForMessage<string>("user/{id}", "1");
|
||||
Assert.AreEqual("Bruno Baïa", result.Body, "Invalid content");
|
||||
Assert.AreEqual(contentType, MediaType.ParseMediaType(result.Headers[HttpResponseHeader.ContentType]), "Invalid content-type");
|
||||
Assert.AreEqual(HttpStatusCode.OK, result.StatusCode, "Invalid status code");
|
||||
Assert.AreEqual("OK", result.StatusDescription, "Invalid status description");
|
||||
}
|
||||
|
||||
[Test]
|
||||
[ExpectedException(typeof(RestClientException),
|
||||
ExpectedMessage = "Could not extract response: no Content-Type found")]
|
||||
public void GetStringNoResponse()
|
||||
{
|
||||
string result = template.GetForObject<string>("/nothing");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void HeadForHeaders()
|
||||
{
|
||||
WebHeaderCollection result = template.HeadForHeaders("head");
|
||||
Assert.AreEqual(new MediaType("text", "plain"), MediaType.ParseMediaType(result[HttpResponseHeader.ContentType]), "Invalid content-type");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PostStringForLocation()
|
||||
{
|
||||
Uri result = template.PostForLocation("user", "Lisa Baia");
|
||||
Assert.AreEqual(new Uri(new Uri(uri), "/user/3"), result, "Invalid location");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PostStringForMessage()
|
||||
{
|
||||
HttpResponseMessage<string> result = template.PostForMessage<string>("user", "Lisa Baia");
|
||||
Assert.AreEqual(new Uri(new Uri(uri), "/user/3"), new Uri(result.Headers[HttpResponseHeader.Location]), "Invalid location");
|
||||
Assert.AreEqual(HttpStatusCode.Created, result.StatusCode, "Invalid status code");
|
||||
Assert.AreEqual("User id '3' created with 'Lisa Baia'", result.StatusDescription, "Invalid status description");
|
||||
Assert.AreEqual("3", result.Body, "Invalid content");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PostStringForObject()
|
||||
{
|
||||
string result = template.PostForObject<string>("user", "Lisa Baia");
|
||||
Assert.AreEqual("3", result, "Invalid content");
|
||||
}
|
||||
|
||||
[Test]
|
||||
[ExpectedException(typeof(RestClientException),
|
||||
ExpectedMessage = "The server returned 'Content cannot be null or empty' with the status code 400 - BadRequest.")]
|
||||
public void PostStringForObjectWithError()
|
||||
{
|
||||
string result = template.PostForObject<string>("user", "");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Put()
|
||||
{
|
||||
string result = template.GetForObject<string>("user/1");
|
||||
Assert.AreEqual("Bruno Baïa", result, "Invalid content");
|
||||
|
||||
template.Put("user/1", "Bruno Baia");
|
||||
|
||||
result = template.GetForObject<string>("user/1");
|
||||
Assert.AreEqual("Bruno Baia", result, "Invalid content");
|
||||
}
|
||||
|
||||
[Test]
|
||||
[ExpectedException(typeof(RestClientException),
|
||||
ExpectedMessage = "The server returned 'User id '4' does not exist' with the status code 400 - BadRequest.")]
|
||||
public void PutWithError()
|
||||
{
|
||||
template.Put("user/4", "Dinora Baia");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Delete()
|
||||
{
|
||||
string result = template.GetForObject<string>("users");
|
||||
Assert.AreEqual("2", result, "Invalid content");
|
||||
|
||||
template.Delete("user/2");
|
||||
|
||||
result = template.GetForObject<string>("users");
|
||||
Assert.AreEqual("1", result, "Invalid content");
|
||||
}
|
||||
|
||||
[Test]
|
||||
[ExpectedException(typeof(RestClientException),
|
||||
ExpectedMessage = "The server returned 'User id '10' does not exist' with the status code 400 - BadRequest.")]
|
||||
public void DeleteWithError()
|
||||
{
|
||||
template.Delete("user/10");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void OptionsForAllow()
|
||||
{
|
||||
IList<HttpMethod> result = template.OptionsForAllow("allow");
|
||||
Assert.AreEqual(3, result.Count, "Invalid response");
|
||||
Assert.IsTrue(result.Contains(HttpMethod.GET), "Invalid response");
|
||||
Assert.IsTrue(result.Contains(HttpMethod.HEAD), "Invalid response");
|
||||
Assert.IsTrue(result.Contains(HttpMethod.PUT), "Invalid response");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ExchangePost()
|
||||
{
|
||||
HttpResponseMessage<string> result = template.Exchange<string>(
|
||||
"user", new HttpRequestMessage("Maryse Baia", HttpMethod.POST));
|
||||
|
||||
Assert.AreEqual("3", result.Body, "Invalid content");
|
||||
Assert.AreEqual(HttpStatusCode.Created, result.StatusCode, "Invalid status code");
|
||||
Assert.AreEqual("User id '3' created with 'Maryse Baia'", result.StatusDescription, "Invalid status description");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ExchangePut()
|
||||
{
|
||||
HttpResponseMessage<string> result = template.Exchange<string>(
|
||||
"user/1", new HttpRequestMessage("Bruno Baia", HttpMethod.PUT));
|
||||
|
||||
Assert.AreEqual(HttpStatusCode.OK, result.StatusCode, "Invalid status code");
|
||||
Assert.AreEqual("User id '1' updated with 'Bruno Baia'", result.StatusDescription, "Invalid status description");
|
||||
}
|
||||
|
||||
[Test]
|
||||
[ExpectedException(ExpectedMessage = "The server returned 'Not Found' with the status code 404 - NotFound.")]
|
||||
public void ClientError()
|
||||
{
|
||||
template.Execute<object>("clienterror", null, null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[ExpectedException(ExpectedMessage = "The server returned 'Internal Server Error' with the status code 500 - InternalServerError.")]
|
||||
public void ServerError()
|
||||
{
|
||||
template.Execute<object>("servererror", null, null);
|
||||
}
|
||||
|
||||
|
||||
//@BeforeClass
|
||||
//public static void startJettyServer() throws Exception {
|
||||
// jettyServer = new Server(8889);
|
||||
// Context jettyContext = new Context(jettyServer, "/");
|
||||
// byte[] bytes = helloWorld.getBytes("UTF-8");
|
||||
// contentType = new MediaType("text", "plain", Collections.singletonMap("charset", "utf-8"));
|
||||
// jettyContext.addServlet(new ServletHolder(new GetServlet(bytes, contentType)), "/get");
|
||||
// jettyContext.addServlet(new ServletHolder(new GetServlet(new byte[0], contentType)), "/get/nothing");
|
||||
// jettyContext.addServlet(
|
||||
// new ServletHolder(new PostServlet(helloWorld, URI + "/post/1", bytes, contentType)),
|
||||
// "/post");
|
||||
// jettyContext.addServlet(new ServletHolder(new ErrorServlet(404)), "/errors/notfound");
|
||||
// jettyContext.addServlet(new ServletHolder(new ErrorServlet(500)), "/errors/server");
|
||||
// jettyContext.addServlet(new ServletHolder(new UriServlet()), "/uri/*");
|
||||
// jettyContext.addServlet(new ServletHolder(new MultipartServlet()), "/multipart");
|
||||
// jettyServer.start();
|
||||
//}
|
||||
|
||||
//@Test
|
||||
//public void uri() throws InterruptedException, URISyntaxException {
|
||||
// String result = template.getForObject(URI + "/uri/{query}", String.class, "Z\u00fcrich");
|
||||
// Assert.AreEqual("Invalid request URI", "/uri/Z%C3%BCrich", result);
|
||||
|
||||
// result = template.getForObject(URI + "/uri/query={query}", String.class, "foo@bar");
|
||||
// Assert.AreEqual("Invalid request URI", "/uri/query=foo@bar", result);
|
||||
|
||||
// result = template.getForObject(URI + "/uri/query={query}", String.class, "T\u014dky\u014d");
|
||||
// Assert.AreEqual("Invalid request URI", "/uri/query=T%C5%8Dky%C5%8D", result);
|
||||
//}
|
||||
|
||||
//@Test
|
||||
//public void multipart() throws UnsupportedEncodingException {
|
||||
// MultiValueMap<String, Object> parts = new LinkedMultiValueMap<String, Object>();
|
||||
// parts.add("name 1", "value 1");
|
||||
// parts.add("name 2", "value 2+1");
|
||||
// parts.add("name 2", "value 2+2");
|
||||
// Resource logo = new ClassPathResource("/org/springframework/http/converter/logo.jpg");
|
||||
// parts.add("logo", logo);
|
||||
|
||||
// template.postForLocation(URI + "/multipart", parts);
|
||||
//}
|
||||
|
||||
|
||||
//private static class UriServlet extends HttpServlet {
|
||||
|
||||
// @Override
|
||||
// protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
// resp.setContentType("text/plain");
|
||||
// resp.setCharacterEncoding("UTF-8");
|
||||
// resp.getWriter().write(req.getRequestURI());
|
||||
// }
|
||||
//}
|
||||
|
||||
//private static class MultipartServlet extends HttpServlet {
|
||||
|
||||
// @Override
|
||||
// protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
// assertTrue(ServletFileUpload.isMultipartContent(req));
|
||||
// FileItemFactory factory = new DiskFileItemFactory();
|
||||
// ServletFileUpload upload = new ServletFileUpload(factory);
|
||||
// try {
|
||||
// List items = upload.parseRequest(req);
|
||||
// Assert.AreEqual(4, items.size());
|
||||
// FileItem item = (FileItem) items.get(0);
|
||||
// assertTrue(item.isFormField());
|
||||
// Assert.AreEqual("name 1", item.getFieldName());
|
||||
// Assert.AreEqual("value 1", item.getString());
|
||||
|
||||
// item = (FileItem) items.get(1);
|
||||
// assertTrue(item.isFormField());
|
||||
// Assert.AreEqual("name 2", item.getFieldName());
|
||||
// Assert.AreEqual("value 2+1", item.getString());
|
||||
|
||||
// item = (FileItem) items.get(2);
|
||||
// assertTrue(item.isFormField());
|
||||
// Assert.AreEqual("name 2", item.getFieldName());
|
||||
// Assert.AreEqual("value 2+2", item.getString());
|
||||
|
||||
// item = (FileItem) items.get(3);
|
||||
// Assert.IsFalse(item.isFormField());
|
||||
// Assert.AreEqual("logo", item.getFieldName());
|
||||
// Assert.AreEqual("logo.jpg", item.getName());
|
||||
// Assert.AreEqual("image/jpeg", item.getContentType());
|
||||
// }
|
||||
// catch (FileUploadException ex) {
|
||||
// throw new ServletException(ex);
|
||||
// }
|
||||
|
||||
// }
|
||||
//}
|
||||
|
||||
#region REST test service
|
||||
|
||||
[ServiceContract]
|
||||
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
|
||||
public class TestService
|
||||
{
|
||||
private IDictionary<string, string> users;
|
||||
|
||||
public TestService()
|
||||
{
|
||||
users = new Dictionary<string, string>();
|
||||
users.Add("1", "Bruno Baïa");
|
||||
users.Add("2", "Marie Baia");
|
||||
}
|
||||
|
||||
[WebGet(UriTemplate = "clienterror")]
|
||||
public void ClientError()
|
||||
{
|
||||
WebOperationContext.Current.OutgoingResponse.SetStatusAsNotFound();
|
||||
}
|
||||
|
||||
[WebGet(UriTemplate = "servererror")]
|
||||
public void ServerError()
|
||||
{
|
||||
WebOperationContext.Current.OutgoingResponse.StatusCode = HttpStatusCode.InternalServerError;
|
||||
}
|
||||
|
||||
[WebInvoke(UriTemplate = "allow", Method = "OPTIONS")]
|
||||
public void Allow()
|
||||
{
|
||||
WebOperationContext.Current.OutgoingResponse.Headers[HttpResponseHeader.Allow] = "GET, HEAD, PUT";
|
||||
}
|
||||
|
||||
[WebInvoke(UriTemplate = "head", Method = "HEAD")]
|
||||
public void Head()
|
||||
{
|
||||
WebOperationContext.Current.OutgoingResponse.Headers[HttpResponseHeader.ContentType] = "text/plain";
|
||||
}
|
||||
|
||||
[WebGet(UriTemplate = "user/{id}")]
|
||||
public Message GetUser(string id)
|
||||
{
|
||||
WebOperationContext context = WebOperationContext.Current;
|
||||
|
||||
if (!users.ContainsKey(id))
|
||||
{
|
||||
context.OutgoingResponse.SetStatusAsNotFound(String.Format("User with id '{0}' not found", id));
|
||||
return context.CreateTextResponse(null);
|
||||
}
|
||||
|
||||
return context.CreateTextResponse(users[id]);
|
||||
}
|
||||
|
||||
[WebGet(UriTemplate = "users")]
|
||||
public Message GetUsersCount()
|
||||
{
|
||||
WebOperationContext context = WebOperationContext.Current;
|
||||
|
||||
return context.CreateTextResponse(users.Count.ToString());
|
||||
}
|
||||
|
||||
[WebGet(UriTemplate = "nothing")]
|
||||
public void GetNothing()
|
||||
{
|
||||
WebOperationContext.Current.OutgoingResponse.SuppressEntityBody = true;
|
||||
}
|
||||
|
||||
[WebInvoke(UriTemplate = "user", Method = "POST")]
|
||||
public Message Post(Stream stream)
|
||||
{
|
||||
WebOperationContext context = WebOperationContext.Current;
|
||||
|
||||
UriTemplateMatch match = context.IncomingRequest.UriTemplateMatch;
|
||||
UriTemplate template = new UriTemplate("/user/{id}");
|
||||
|
||||
MediaType mediaType = MediaType.ParseMediaType(context.IncomingRequest.ContentType);
|
||||
|
||||
string id = (users.Count + 1).ToString(); // generate new ID
|
||||
string name;
|
||||
using (StreamReader reader = new StreamReader(stream, Encoding.GetEncoding(mediaType.CharSet)))
|
||||
{
|
||||
name = reader.ReadToEnd();
|
||||
}
|
||||
|
||||
if (String.IsNullOrEmpty(name))
|
||||
{
|
||||
context.OutgoingResponse.StatusCode = HttpStatusCode.BadRequest;
|
||||
context.OutgoingResponse.StatusDescription = "Content cannot be null or empty";
|
||||
return WebOperationContext.Current.CreateTextResponse("");
|
||||
}
|
||||
|
||||
users.Add(id, name);
|
||||
|
||||
Uri uri = template.BindByPosition(match.BaseUri, id);
|
||||
context.OutgoingResponse.SetStatusAsCreated(uri);
|
||||
context.OutgoingResponse.StatusDescription = String.Format("User id '{0}' created with '{1}'", id, name);
|
||||
|
||||
return WebOperationContext.Current.CreateTextResponse(id);
|
||||
}
|
||||
|
||||
[WebInvoke(UriTemplate = "user/{id}", Method = "PUT")]
|
||||
public void Update(string id, Stream stream)
|
||||
{
|
||||
WebOperationContext context = WebOperationContext.Current;
|
||||
|
||||
if (!users.ContainsKey(id))
|
||||
{
|
||||
context.OutgoingResponse.StatusCode = HttpStatusCode.BadRequest;
|
||||
context.OutgoingResponse.StatusDescription = String.Format("User id '{0}' does not exist", id);
|
||||
return;
|
||||
}
|
||||
|
||||
MediaType mediaType = MediaType.ParseMediaType(context.IncomingRequest.ContentType);
|
||||
|
||||
string name;
|
||||
using (StreamReader reader = new StreamReader(stream, Encoding.GetEncoding(mediaType.CharSet)))
|
||||
{
|
||||
name = reader.ReadToEnd();
|
||||
}
|
||||
users[id] = name;
|
||||
|
||||
context.OutgoingResponse.StatusCode = HttpStatusCode.OK;
|
||||
context.OutgoingResponse.StatusDescription = String.Format("User id '{0}' updated with '{1}'", id, name);
|
||||
//context.OutgoingResponse.ContentType = "text/plain";
|
||||
}
|
||||
|
||||
[WebInvoke(UriTemplate = "user/{id}", Method = "DELETE")]
|
||||
public void Delete(string id)
|
||||
{
|
||||
WebOperationContext context = WebOperationContext.Current;
|
||||
|
||||
if (!users.ContainsKey(id))
|
||||
{
|
||||
context.OutgoingResponse.StatusCode = HttpStatusCode.BadRequest;
|
||||
context.OutgoingResponse.StatusDescription = String.Format("User id '{0}' does not exist", id);
|
||||
return;
|
||||
}
|
||||
|
||||
users.Remove(id);
|
||||
|
||||
context.OutgoingResponse.StatusCode = HttpStatusCode.OK;
|
||||
context.OutgoingResponse.StatusDescription = String.Format("User id '{0}' have been removed", id);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
#endif
|
||||
643
test/Spring/Spring.Http.Tests/Http/Rest/RestTemplateTests.cs
Normal file
643
test/Spring/Spring.Http.Tests/Http/Rest/RestTemplateTests.cs
Normal file
@@ -0,0 +1,643 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Spring.Http;
|
||||
using Spring.Http.Converters;
|
||||
|
||||
using NUnit.Framework;
|
||||
using Rhino.Mocks;
|
||||
|
||||
namespace Spring.Http.Rest
|
||||
{
|
||||
/// <summary>
|
||||
/// Unit tests for the RestTemplate class.
|
||||
/// </summary>
|
||||
/// <author>Arjen Poutsma</author>
|
||||
/// <author>Bruno Baia (.NET)</author>
|
||||
[TestFixture]
|
||||
public class RestTemplateTests
|
||||
{
|
||||
#region Logging
|
||||
|
||||
private static readonly Common.Logging.ILog LOG = Common.Logging.LogManager.GetLogger(typeof(RestTemplateTests));
|
||||
|
||||
#endregion
|
||||
|
||||
private MockRepository mocks;
|
||||
private RestTemplate template;
|
||||
private IHttpWebRequestFactory requestFactory;
|
||||
private HttpWebRequest request;
|
||||
private HttpWebResponse response;
|
||||
//private ResponseErrorHandler errorHandler;
|
||||
private IHttpMessageConverter converter;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
mocks = new MockRepository();
|
||||
requestFactory = mocks.CreateMock<IHttpWebRequestFactory>();
|
||||
request = mocks.CreateMock<HttpWebRequest>();
|
||||
response = mocks.CreateMock<HttpWebResponse>();
|
||||
//errorHandler = createMock(ResponseErrorHandler.class);
|
||||
converter = mocks.CreateMock<IHttpMessageConverter>();
|
||||
|
||||
IList<IHttpMessageConverter> messageConverters = new List<IHttpMessageConverter>(1);
|
||||
messageConverters.Add(converter);
|
||||
|
||||
template = new RestTemplate();
|
||||
template.RequestFactory = requestFactory;
|
||||
template.MessageConverters = messageConverters;
|
||||
//template.setErrorHandler(errorHandler);
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TearDown()
|
||||
{
|
||||
mocks.VerifyAll();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void VarArgsTemplateVariables()
|
||||
{
|
||||
Expect.Call<HttpWebRequest>(requestFactory.CreateRequest(new Uri("http://example.com/hotels/42/bookings/21")))
|
||||
.Return(request);
|
||||
ExpectGetResponse();
|
||||
//Expect.Call(errorHandler.hasError(response)).andReturn(false);
|
||||
|
||||
mocks.ReplayAll();
|
||||
|
||||
template.Execute<object>("http://example.com/hotels/{hotel}/bookings/{booking}", null, null, "42", "21");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DictionaryTemplateVariables()
|
||||
{
|
||||
Expect.Call<HttpWebRequest>(requestFactory.CreateRequest(new Uri("http://example.com/hotels/42/bookings/21")))
|
||||
.Return(request);
|
||||
ExpectGetResponse();
|
||||
//Expect.Call(errorHandler.hasError(response)).andReturn(false);
|
||||
|
||||
mocks.ReplayAll();
|
||||
|
||||
IDictionary<string, string> variables = new Dictionary<string, string>();
|
||||
variables.Add("booking", "41");
|
||||
variables.Add("hotel", "42");
|
||||
template.Execute<object>("http://example.com/hotels/{hotel}/bookings/{booking}", null, null, "42", "21");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BaseAddressTemplate()
|
||||
{
|
||||
Expect.Call<HttpWebRequest>(requestFactory.CreateRequest(new Uri("http://example.com/hotels/42/bookings/21")))
|
||||
.Return(request);
|
||||
ExpectGetResponse();
|
||||
//Expect.Call(errorHandler.hasError(response)).andReturn(false);
|
||||
|
||||
mocks.ReplayAll();
|
||||
|
||||
template.BaseAddress = new Uri("http://example.com");
|
||||
template.Execute<object>("hotels/{hotel}/bookings/{booking}", null, null, "42", "21");
|
||||
}
|
||||
|
||||
//[Test]
|
||||
//public void errorHandling() {
|
||||
// Expect.Call(requestFactory.createRequest(new URI("http://example.com"), HttpMethod.GET)).andReturn(request);
|
||||
// Expect.Call(request.execute()).andReturn(response);
|
||||
// Expect.Call(errorHandler.hasError(response)).andReturn(true);
|
||||
// Expect.Call(response.getStatusCode()).andReturn(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
// Expect.Call(response.getStatusText()).andReturn("Internal Server Error");
|
||||
// errorHandler.handleError(response);
|
||||
// expectLastCall().andThrow(new HttpServerErrorException(HttpStatus.INTERNAL_SERVER_ERROR));
|
||||
// response.close();
|
||||
|
||||
// mocks.ReplayAll();
|
||||
|
||||
// try {
|
||||
// template.execute("http://example.com", HttpMethod.GET, null, null);
|
||||
// fail("HttpServerErrorException expected");
|
||||
// }
|
||||
// catch (HttpServerErrorException ex) {
|
||||
// // expected
|
||||
// }
|
||||
// mocks.ReplayAll();
|
||||
//}
|
||||
|
||||
[Test]
|
||||
public void GetForObject()
|
||||
{
|
||||
Expect.Call<bool>(converter.CanRead(typeof(string), null)).Return(true);
|
||||
MediaType textPlain = new MediaType("text", "plain");
|
||||
IList<MediaType> mediaTypes = new List<MediaType>(1);
|
||||
mediaTypes.Add(textPlain);
|
||||
Expect.Call<IList<MediaType>>(converter.SupportedMediaTypes).Return(mediaTypes);
|
||||
Expect.Call<HttpWebRequest>(requestFactory.CreateRequest(new Uri("http://example.com"))).Return(request);
|
||||
Expect.Call(request.Method = "GET");
|
||||
Expect.Call(request.Accept = "text/plain");
|
||||
WebHeaderCollection requestHeaders = new WebHeaderCollection();
|
||||
Expect.Call<WebHeaderCollection>(request.Headers).Return(requestHeaders).Repeat.Any();
|
||||
ExpectGetResponse();
|
||||
//Expect.Call(errorHandler.hasError(response)).andReturn(false);
|
||||
WebHeaderCollection responseHeaders = new WebHeaderCollection();
|
||||
responseHeaders[HttpResponseHeader.ContentType] = textPlain.ToString();
|
||||
Expect.Call<WebHeaderCollection>(response.Headers).Return(responseHeaders).Repeat.Any();
|
||||
Expect.Call<bool>(converter.CanRead(typeof(string), textPlain)).Return(true);
|
||||
String expected = "Hello World";
|
||||
Expect.Call<string>(converter.Read<string>(response)).Return(expected);
|
||||
|
||||
mocks.ReplayAll();
|
||||
|
||||
string result = template.GetForObject<string>("http://example.com");
|
||||
Assert.AreEqual(expected, result, "Invalid GET result");
|
||||
}
|
||||
|
||||
[Test]
|
||||
[ExpectedException(typeof(RestClientException),
|
||||
ExpectedMessage = "Could not extract response: no suitable HttpMessageConverter found for response type [System.String] and content type [bar/baz]")]
|
||||
public void GetUnsupportedMediaType()
|
||||
{
|
||||
Expect.Call<bool>(converter.CanRead(typeof(string), null)).Return(true);
|
||||
MediaType textPlain = new MediaType("foo", "bar");
|
||||
IList<MediaType> mediaTypes = new List<MediaType>(1);
|
||||
mediaTypes.Add(textPlain);
|
||||
Expect.Call<IList<MediaType>>(converter.SupportedMediaTypes).Return(mediaTypes);
|
||||
Expect.Call<HttpWebRequest>(requestFactory.CreateRequest(new Uri("http://example.com/resource"))).Return(request);
|
||||
Expect.Call(request.Method = "GET");
|
||||
Expect.Call(request.Accept = "foo/bar");
|
||||
WebHeaderCollection requestHeaders = new WebHeaderCollection();
|
||||
Expect.Call<WebHeaderCollection>(request.Headers).Return(requestHeaders).Repeat.Any();
|
||||
ExpectGetResponse();
|
||||
//Expect.Call(errorHandler.hasError(response)).andReturn(false);
|
||||
WebHeaderCollection responseHeaders = new WebHeaderCollection();
|
||||
MediaType contentType = new MediaType("bar", "baz");
|
||||
responseHeaders[HttpResponseHeader.ContentType] = contentType.ToString();
|
||||
Expect.Call<WebHeaderCollection>(response.Headers).Return(responseHeaders).Repeat.Any();
|
||||
Expect.Call<bool>(converter.CanRead(typeof(string), contentType)).Return(false);
|
||||
|
||||
mocks.ReplayAll();
|
||||
|
||||
template.GetForObject<string>("http://example.com/{p}", "resource");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetForMessage()
|
||||
{
|
||||
Expect.Call<bool>(converter.CanRead(typeof(string), null)).Return(true);
|
||||
MediaType textPlain = new MediaType("text", "plain");
|
||||
IList<MediaType> mediaTypes = new List<MediaType>(1);
|
||||
mediaTypes.Add(textPlain);
|
||||
Expect.Call<IList<MediaType>>(converter.SupportedMediaTypes).Return(mediaTypes);
|
||||
Expect.Call<HttpWebRequest>(requestFactory.CreateRequest(new Uri("http://example.com"))).Return(request);
|
||||
Expect.Call(request.Method = "GET");
|
||||
Expect.Call(request.Accept = "text/plain");
|
||||
WebHeaderCollection requestHeaders = new WebHeaderCollection();
|
||||
Expect.Call<WebHeaderCollection>(request.Headers).Return(requestHeaders).Repeat.Any();
|
||||
ExpectGetResponse();
|
||||
//Expect.Call(errorHandler.hasError(response)).andReturn(false);
|
||||
WebHeaderCollection responseHeaders = new WebHeaderCollection();
|
||||
responseHeaders[HttpResponseHeader.ContentType] = textPlain.ToString();
|
||||
Expect.Call<WebHeaderCollection>(response.Headers).Return(responseHeaders).Repeat.Any();
|
||||
Expect.Call<bool>(converter.CanRead(typeof(string), textPlain)).Return(true);
|
||||
String expected = "Hello World";
|
||||
Expect.Call<string>(converter.Read<string>(response)).Return(expected);
|
||||
Expect.Call<HttpStatusCode>(response.StatusCode).Return(HttpStatusCode.OK);
|
||||
Expect.Call<string>(response.StatusDescription).Return("OK");
|
||||
|
||||
mocks.ReplayAll();
|
||||
|
||||
HttpResponseMessage<String> result = template.GetForMessage<string>("http://example.com");
|
||||
Assert.AreEqual(expected, result.Body, "Invalid GET result");
|
||||
Assert.AreEqual(textPlain.ToString(), result.Headers[HttpResponseHeader.ContentType], "Invalid Content-Type header");
|
||||
Assert.AreEqual(HttpStatusCode.OK, result.StatusCode, "Invalid status code");
|
||||
Assert.AreEqual("OK", result.StatusDescription, "Invalid status description");
|
||||
|
||||
mocks.ReplayAll();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void HeadForHeaders()
|
||||
{
|
||||
Expect.Call<HttpWebRequest>(requestFactory.CreateRequest(new Uri("http://example.com"))).Return(request);
|
||||
Expect.Call(request.Method = "HEAD");
|
||||
ExpectGetResponse();
|
||||
//Expect.Call(errorHandler.hasError(response)).andReturn(false);
|
||||
WebHeaderCollection responseHeaders = new WebHeaderCollection();
|
||||
Expect.Call<WebHeaderCollection>(response.Headers).Return(responseHeaders).Repeat.Any();
|
||||
|
||||
mocks.ReplayAll();
|
||||
|
||||
WebHeaderCollection result = template.HeadForHeaders("http://example.com");
|
||||
|
||||
Assert.AreSame(responseHeaders, result, "Invalid headers returned");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PostForLocation()
|
||||
{
|
||||
string helloWorld = "Hello World";
|
||||
Expect.Call<HttpWebRequest>(requestFactory.CreateRequest(new Uri("http://example.com"))).Return(request);
|
||||
Expect.Call(request.Method = "POST");
|
||||
Expect.Call<bool>(converter.CanWrite(typeof(string), null)).Return(true);
|
||||
converter.Write(helloWorld, null, request);
|
||||
ExpectGetResponse();
|
||||
//Expect.Call(errorHandler.hasError(response)).andReturn(false);
|
||||
WebHeaderCollection responseHeaders = new WebHeaderCollection();
|
||||
Uri expected = new Uri("http://example.com/hotels");
|
||||
responseHeaders[HttpResponseHeader.Location] = expected.ToString();
|
||||
Expect.Call<WebHeaderCollection>(response.Headers).Return(responseHeaders).Repeat.Any();
|
||||
|
||||
mocks.ReplayAll();
|
||||
|
||||
Uri result = template.PostForLocation("http://example.com", helloWorld);
|
||||
Assert.AreEqual(expected, result, "Invalid POST result");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PostForLocationMessageContentType()
|
||||
{
|
||||
string helloWorld = "Hello World";
|
||||
Expect.Call<HttpWebRequest>(requestFactory.CreateRequest(new Uri("http://example.com"))).Return(request);
|
||||
Expect.Call(request.Method = "POST");
|
||||
MediaType contentType = new MediaType("text", "plain");
|
||||
Expect.Call<bool>(converter.CanWrite(typeof(string), contentType)).Return(true);
|
||||
WebHeaderCollection requestHeaders = new WebHeaderCollection();
|
||||
Expect.Call<WebHeaderCollection>(request.Headers).Return(requestHeaders).Repeat.Any();
|
||||
converter.Write(helloWorld, contentType, request);
|
||||
ExpectGetResponse();
|
||||
//Expect.Call(errorHandler.hasError(response)).andReturn(false);
|
||||
WebHeaderCollection responseHeaders = new WebHeaderCollection();
|
||||
Uri expected = new Uri("http://example.com/hotels");
|
||||
responseHeaders[HttpResponseHeader.Location] = expected.ToString();
|
||||
Expect.Call<WebHeaderCollection>(response.Headers).Return(responseHeaders).Repeat.Any();
|
||||
|
||||
mocks.ReplayAll();
|
||||
|
||||
WebHeaderCollection requestMessageHeaders = new WebHeaderCollection();
|
||||
requestMessageHeaders[HttpRequestHeader.ContentType] = contentType.ToString();
|
||||
HttpRequestMessage requestMessage = new HttpRequestMessage(helloWorld, requestMessageHeaders);
|
||||
|
||||
Uri result = template.PostForLocation("http://example.com", requestMessage);
|
||||
Assert.AreEqual(expected, result, "Invalid POST result");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PostForLocationEntityCustomHeader()
|
||||
{
|
||||
string helloWorld = "Hello World";
|
||||
Expect.Call<HttpWebRequest>(requestFactory.CreateRequest(new Uri("http://example.com"))).Return(request);
|
||||
Expect.Call(request.Method = "POST");
|
||||
Expect.Call<bool>(converter.CanWrite(typeof(string), null)).Return(true);
|
||||
WebHeaderCollection requestHeaders = new WebHeaderCollection();
|
||||
Expect.Call<WebHeaderCollection>(request.Headers).Return(requestHeaders).Repeat.Any();
|
||||
converter.Write(helloWorld, null, request);
|
||||
ExpectGetResponse();
|
||||
//Expect.Call(errorHandler.hasError(response)).andReturn(false);
|
||||
WebHeaderCollection responseHeaders = new WebHeaderCollection();
|
||||
Uri expected = new Uri("http://example.com/hotels");
|
||||
responseHeaders[HttpResponseHeader.Location] = expected.ToString();
|
||||
Expect.Call<WebHeaderCollection>(response.Headers).Return(responseHeaders).Repeat.Any();
|
||||
|
||||
mocks.ReplayAll();
|
||||
|
||||
WebHeaderCollection requestMessageHeaders = new WebHeaderCollection();
|
||||
requestMessageHeaders.Add("MyHeader", "MyValue");
|
||||
HttpRequestMessage requestMessage = new HttpRequestMessage(helloWorld, requestMessageHeaders);
|
||||
|
||||
Uri result = template.PostForLocation("http://example.com", requestMessage);
|
||||
Assert.AreEqual(expected, result, "Invalid POST result");
|
||||
Assert.AreEqual("MyValue", requestHeaders.Get("MyHeader"), "No custom header set");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PostForLocationNoLocation()
|
||||
{
|
||||
string helloWorld = "Hello World";
|
||||
Expect.Call<HttpWebRequest>(requestFactory.CreateRequest(new Uri("http://example.com"))).Return(request);
|
||||
Expect.Call(request.Method = "POST");
|
||||
Expect.Call<bool>(converter.CanWrite(typeof(string), null)).Return(true);
|
||||
converter.Write(helloWorld, null, request);
|
||||
ExpectGetResponse();
|
||||
//Expect.Call(errorHandler.hasError(response)).andReturn(false);
|
||||
WebHeaderCollection responseHeaders = new WebHeaderCollection();
|
||||
Expect.Call<WebHeaderCollection>(response.Headers).Return(responseHeaders).Repeat.Any();
|
||||
|
||||
mocks.ReplayAll();
|
||||
|
||||
Uri result = template.PostForLocation("http://example.com", helloWorld);
|
||||
Assert.IsNull(result, "Invalid POST result");
|
||||
|
||||
mocks.ReplayAll();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PostForLocationNull()
|
||||
{
|
||||
Expect.Call<HttpWebRequest>(requestFactory.CreateRequest(new Uri("http://example.com"))).Return(request);
|
||||
Expect.Call(request.Method = "POST");
|
||||
WebHeaderCollection requestHeaders = new WebHeaderCollection();
|
||||
Expect.Call<WebHeaderCollection>(request.Headers).Return(requestHeaders).Repeat.Any();
|
||||
ExpectGetResponse();
|
||||
//Expect.Call(errorHandler.hasError(response)).andReturn(false);
|
||||
WebHeaderCollection responseHeaders = new WebHeaderCollection();
|
||||
Expect.Call<WebHeaderCollection>(response.Headers).Return(responseHeaders).Repeat.Any();
|
||||
|
||||
mocks.ReplayAll();
|
||||
|
||||
template.PostForLocation("http://example.com", null);
|
||||
Assert.IsNull(requestHeaders[HttpRequestHeader.ContentLength], "Invalid content length");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PostForObject()
|
||||
{
|
||||
Expect.Call<bool>(converter.CanRead(typeof(Version), null)).Return(true);
|
||||
MediaType textPlain = new MediaType("text", "plain");
|
||||
IList<MediaType> mediaTypes = new List<MediaType>(1);
|
||||
mediaTypes.Add(textPlain);
|
||||
Expect.Call<IList<MediaType>>(converter.SupportedMediaTypes).Return(mediaTypes);
|
||||
Expect.Call<HttpWebRequest>(requestFactory.CreateRequest(new Uri("http://example.com"))).Return(request);
|
||||
Expect.Call(request.Method = "POST");
|
||||
Expect.Call(request.Accept = "text/plain");
|
||||
WebHeaderCollection requestHeaders = new WebHeaderCollection();
|
||||
Expect.Call<WebHeaderCollection>(request.Headers).Return(requestHeaders).Repeat.Any();
|
||||
string helloWorld = "Hello World";
|
||||
Expect.Call<bool>(converter.CanWrite(typeof(string), null)).Return(true);
|
||||
converter.Write(helloWorld, null, request);
|
||||
ExpectGetResponse();
|
||||
//Expect.Call(errorHandler.hasError(response)).andReturn(false);
|
||||
WebHeaderCollection responseHeaders = new WebHeaderCollection();
|
||||
responseHeaders[HttpResponseHeader.ContentType] = textPlain.ToString();
|
||||
Expect.Call<WebHeaderCollection>(response.Headers).Return(responseHeaders).Repeat.Any();
|
||||
Version expected = new Version(1, 0);
|
||||
Expect.Call<bool>(converter.CanRead(typeof(Version), textPlain)).Return(true);
|
||||
Expect.Call<Version>(converter.Read<Version>(response)).Return(expected);
|
||||
|
||||
mocks.ReplayAll();
|
||||
|
||||
Version result = template.PostForObject<Version>("http://example.com", helloWorld);
|
||||
Assert.AreEqual(expected, result, "Invalid POST result");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PostForEntity()
|
||||
{
|
||||
Expect.Call<bool>(converter.CanRead(typeof(Version), null)).Return(true);
|
||||
MediaType textPlain = new MediaType("text", "plain");
|
||||
IList<MediaType> mediaTypes = new List<MediaType>(1);
|
||||
mediaTypes.Add(textPlain);
|
||||
Expect.Call<IList<MediaType>>(converter.SupportedMediaTypes).Return(mediaTypes);
|
||||
Expect.Call<HttpWebRequest>(requestFactory.CreateRequest(new Uri("http://example.com"))).Return(request);
|
||||
Expect.Call(request.Method = "POST");
|
||||
Expect.Call(request.Accept = "text/plain");
|
||||
WebHeaderCollection requestHeaders = new WebHeaderCollection();
|
||||
Expect.Call<WebHeaderCollection>(request.Headers).Return(requestHeaders).Repeat.Any();
|
||||
string helloWorld = "Hello World";
|
||||
Expect.Call<bool>(converter.CanWrite(typeof(string), null)).Return(true);
|
||||
converter.Write(helloWorld, null, request);
|
||||
ExpectGetResponse();
|
||||
//Expect.Call(errorHandler.hasError(response)).andReturn(false);
|
||||
WebHeaderCollection responseHeaders = new WebHeaderCollection();
|
||||
responseHeaders[HttpResponseHeader.ContentType] = textPlain.ToString();
|
||||
Expect.Call<WebHeaderCollection>(response.Headers).Return(responseHeaders).Repeat.Any();
|
||||
Version expected = new Version(1, 0);
|
||||
Expect.Call<bool>(converter.CanRead(typeof(Version), textPlain)).Return(true);
|
||||
Expect.Call<Version>(converter.Read<Version>(response)).Return(expected);
|
||||
Expect.Call<HttpStatusCode>(response.StatusCode).Return(HttpStatusCode.OK);
|
||||
Expect.Call<string>(response.StatusDescription).Return("OK");
|
||||
|
||||
mocks.ReplayAll();
|
||||
|
||||
HttpResponseMessage<Version> result = template.PostForMessage<Version>("http://example.com", helloWorld);
|
||||
Assert.AreEqual(expected, result.Body, "Invalid POST result");
|
||||
Assert.AreEqual(textPlain, MediaType.ParseMediaType(result.Headers[HttpResponseHeader.ContentType]), "Invalid Content-Type");
|
||||
Assert.AreEqual(HttpStatusCode.OK, result.StatusCode, "Invalid status code");
|
||||
Assert.AreEqual("OK", result.StatusDescription, "Invalid status description");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PostForObjectNull()
|
||||
{
|
||||
Expect.Call<bool>(converter.CanRead(typeof(Version), null)).Return(true);
|
||||
MediaType textPlain = new MediaType("text", "plain");
|
||||
IList<MediaType> mediaTypes = new List<MediaType>(1);
|
||||
mediaTypes.Add(textPlain);
|
||||
Expect.Call<IList<MediaType>>(converter.SupportedMediaTypes).Return(mediaTypes);
|
||||
Expect.Call<HttpWebRequest>(requestFactory.CreateRequest(new Uri("http://example.com"))).Return(request);
|
||||
Expect.Call(request.Method = "POST");
|
||||
Expect.Call(request.Accept = "text/plain");
|
||||
WebHeaderCollection requestHeaders = new WebHeaderCollection();
|
||||
Expect.Call<WebHeaderCollection>(request.Headers).Return(requestHeaders).Repeat.Any();
|
||||
ExpectGetResponse();
|
||||
//Expect.Call(errorHandler.hasError(response)).andReturn(false);
|
||||
WebHeaderCollection responseHeaders = new WebHeaderCollection();
|
||||
responseHeaders[HttpResponseHeader.ContentType] = textPlain.ToString();
|
||||
Expect.Call<WebHeaderCollection>(response.Headers).Return(responseHeaders).Repeat.Any();
|
||||
Expect.Call<bool>(converter.CanRead(typeof(Version), textPlain)).Return(true);
|
||||
Expect.Call<Version>(converter.Read<Version>(response)).Return(null);
|
||||
|
||||
mocks.ReplayAll();
|
||||
|
||||
Version result = template.PostForObject<Version>("http://example.com", null);
|
||||
Assert.IsNull(result, "Invalid POST result");
|
||||
Assert.IsNull(requestHeaders[HttpRequestHeader.ContentLength], "Invalid content length");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PostForEntityNull()
|
||||
{
|
||||
Expect.Call<bool>(converter.CanRead(typeof(Version), null)).Return(true);
|
||||
MediaType textPlain = new MediaType("text", "plain");
|
||||
IList<MediaType> mediaTypes = new List<MediaType>(1);
|
||||
mediaTypes.Add(textPlain);
|
||||
Expect.Call<IList<MediaType>>(converter.SupportedMediaTypes).Return(mediaTypes);
|
||||
Expect.Call<HttpWebRequest>(requestFactory.CreateRequest(new Uri("http://example.com"))).Return(request);
|
||||
Expect.Call(request.Method = "POST");
|
||||
Expect.Call(request.Accept = "text/plain");
|
||||
WebHeaderCollection requestHeaders = new WebHeaderCollection();
|
||||
Expect.Call<WebHeaderCollection>(request.Headers).Return(requestHeaders).Repeat.Any();
|
||||
ExpectGetResponse();
|
||||
//Expect.Call(errorHandler.hasError(response)).andReturn(false);
|
||||
WebHeaderCollection responseHeaders = new WebHeaderCollection();
|
||||
responseHeaders[HttpResponseHeader.ContentType] = textPlain.ToString();
|
||||
Expect.Call<WebHeaderCollection>(response.Headers).Return(responseHeaders).Repeat.Any();
|
||||
Expect.Call<bool>(converter.CanRead(typeof(Version), textPlain)).Return(true);
|
||||
Expect.Call<Version>(converter.Read<Version>(response)).Return(null);
|
||||
Expect.Call<HttpStatusCode>(response.StatusCode).Return(HttpStatusCode.OK);
|
||||
Expect.Call<string>(response.StatusDescription).Return("OK");
|
||||
|
||||
mocks.ReplayAll();
|
||||
|
||||
HttpResponseMessage<Version> result = template.PostForMessage<Version>("http://example.com", null);
|
||||
Assert.IsNull(result.Body, "Invalid POST result");
|
||||
Assert.AreEqual(textPlain, MediaType.ParseMediaType(result.Headers[HttpResponseHeader.ContentType]), "Invalid Content-Type");
|
||||
Assert.IsNull(requestHeaders[HttpRequestHeader.ContentLength], "Invalid content length");
|
||||
Assert.AreEqual(HttpStatusCode.OK, result.StatusCode, "Invalid status code");
|
||||
Assert.AreEqual("OK", result.StatusDescription, "Invalid status description");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Put()
|
||||
{
|
||||
Expect.Call<bool>(converter.CanWrite(typeof(string), null)).Return(true);
|
||||
Expect.Call<HttpWebRequest>(requestFactory.CreateRequest(new Uri("http://example.com"))).Return(request);
|
||||
Expect.Call(request.Method = "PUT");
|
||||
string helloWorld = "Hello World";
|
||||
converter.Write(helloWorld, null, request);
|
||||
ExpectGetResponse();
|
||||
//Expect.Call(errorHandler.hasError(response)).andReturn(false);
|
||||
|
||||
mocks.ReplayAll();
|
||||
|
||||
template.Put("http://example.com", helloWorld);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PutNull()
|
||||
{
|
||||
Expect.Call<HttpWebRequest>(requestFactory.CreateRequest(new Uri("http://example.com"))).Return(request);
|
||||
Expect.Call(request.Method = "PUT");
|
||||
WebHeaderCollection requestHeaders = new WebHeaderCollection();
|
||||
Expect.Call<WebHeaderCollection>(request.Headers).Return(requestHeaders).Repeat.Any();
|
||||
ExpectGetResponse();
|
||||
//Expect.Call(errorHandler.hasError(response)).andReturn(false);
|
||||
|
||||
mocks.ReplayAll();
|
||||
|
||||
template.Put("http://example.com", null);
|
||||
|
||||
Assert.IsNull(requestHeaders[HttpRequestHeader.ContentLength], "Invalid content length");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Delete()
|
||||
{
|
||||
Expect.Call<HttpWebRequest>(requestFactory.CreateRequest(new Uri("http://example.com"))).Return(request);
|
||||
Expect.Call(request.Method = "DELETE");
|
||||
ExpectGetResponse();
|
||||
//Expect.Call(errorHandler.hasError(response)).andReturn(false);
|
||||
|
||||
mocks.ReplayAll();
|
||||
|
||||
template.Delete("http://example.com");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void OptionsForAllow()
|
||||
{
|
||||
Expect.Call<HttpWebRequest>(requestFactory.CreateRequest(new Uri("http://example.com"))).Return(request);
|
||||
Expect.Call(request.Method = "OPTIONS");
|
||||
ExpectGetResponse();
|
||||
//Expect.Call(errorHandler.hasError(response)).andReturn(false);
|
||||
WebHeaderCollection responseHeaders = new WebHeaderCollection();
|
||||
responseHeaders[HttpResponseHeader.Allow] = "GET,POST";
|
||||
Expect.Call<WebHeaderCollection>(response.Headers).Return(responseHeaders).Repeat.Any();
|
||||
|
||||
mocks.ReplayAll();
|
||||
|
||||
IList<HttpMethod> result = template.OptionsForAllow("http://example.com");
|
||||
Assert.AreEqual(2, result.Count, "Invalid OPTIONS result");
|
||||
Assert.IsTrue(result.Contains(HttpMethod.GET), "Invalid OPTIONS result");
|
||||
Assert.IsTrue(result.Contains(HttpMethod.POST), "Invalid OPTIONS result");
|
||||
}
|
||||
|
||||
//[Test]
|
||||
//public void ioException() {
|
||||
// Expect.Call(converter.canRead(String.class, null)).andReturn(true);
|
||||
// MediaType mediaType = new MediaType("foo", "bar");
|
||||
// Expect.Call(converter.getSupportedMediaTypes()).andReturn(Collections.singletonList(mediaType));
|
||||
// Expect.Call(requestFactory.createRequest(new URI("http://example.com/resource"), HttpMethod.GET)).andReturn(request);
|
||||
// Expect.Call(request.getHeaders()).andReturn(new HttpHeaders());
|
||||
// Expect.Call(request.execute()).andThrow(new IOException());
|
||||
|
||||
// mocks.ReplayAll();
|
||||
|
||||
// try {
|
||||
// template.getForObject("http://example.com/resource", String.class);
|
||||
// fail("RestClientException expected");
|
||||
// }
|
||||
// catch (ResourceAccessException ex) {
|
||||
// // expected
|
||||
// }
|
||||
|
||||
// mocks.ReplayAll();
|
||||
//}
|
||||
|
||||
[Test]
|
||||
public void Exchange()
|
||||
{
|
||||
Expect.Call<bool>(converter.CanRead(typeof(Version), null)).Return(true);
|
||||
MediaType textPlain = new MediaType("text", "plain");
|
||||
IList<MediaType> mediaTypes = new List<MediaType>(1);
|
||||
mediaTypes.Add(textPlain);
|
||||
Expect.Call<IList<MediaType>>(converter.SupportedMediaTypes).Return(mediaTypes);
|
||||
Expect.Call<HttpWebRequest>(requestFactory.CreateRequest(new Uri("http://example.com"))).Return(request);
|
||||
Expect.Call(request.Method = "POST");
|
||||
Expect.Call(request.Accept = "text/plain");
|
||||
WebHeaderCollection requestHeaders = new WebHeaderCollection();
|
||||
Expect.Call<WebHeaderCollection>(request.Headers).Return(requestHeaders).Repeat.Any();
|
||||
string helloWorld = "Hello World";
|
||||
Expect.Call<bool>(converter.CanWrite(typeof(string), null)).Return(true);
|
||||
converter.Write(helloWorld, null, request);
|
||||
ExpectGetResponse();
|
||||
//Expect.Call(errorHandler.hasError(response)).andReturn(false);
|
||||
WebHeaderCollection responseHeaders = new WebHeaderCollection();
|
||||
responseHeaders[HttpResponseHeader.ContentType] = textPlain.ToString();
|
||||
Expect.Call<WebHeaderCollection>(response.Headers).Return(responseHeaders).Repeat.Any();
|
||||
Version expected = new Version(1, 0);
|
||||
Expect.Call<bool>(converter.CanRead(typeof(Version), textPlain)).Return(true);
|
||||
Expect.Call<Version>(converter.Read<Version>(response)).Return(expected);
|
||||
Expect.Call<HttpStatusCode>(response.StatusCode).Return(HttpStatusCode.OK);
|
||||
Expect.Call<string>(response.StatusDescription).Return("OK");
|
||||
|
||||
mocks.ReplayAll();
|
||||
|
||||
WebHeaderCollection requestMessageHeaders = new WebHeaderCollection();
|
||||
requestMessageHeaders.Add("MyHeader", "MyValue");
|
||||
HttpRequestMessage requestMessage = new HttpRequestMessage(helloWorld, requestMessageHeaders, HttpMethod.POST);
|
||||
HttpResponseMessage<Version> result = template.Exchange<Version>("http://example.com", requestMessage);
|
||||
Assert.AreEqual(expected, result.Body, "Invalid POST result");
|
||||
Assert.AreEqual(textPlain, MediaType.ParseMediaType(result.Headers[HttpResponseHeader.ContentType]), "Invalid Content-Type");
|
||||
Assert.AreEqual("MyValue", requestHeaders.Get("MyHeader"), "No custom header set");
|
||||
Assert.AreEqual(HttpStatusCode.OK, result.StatusCode, "Invalid status code");
|
||||
Assert.AreEqual("OK", result.StatusDescription, "Invalid status description");
|
||||
}
|
||||
|
||||
#region Utility methods
|
||||
|
||||
private void ExpectGetResponse()
|
||||
{
|
||||
Expect.Call<WebResponse>(request.GetResponse()).Return(response);
|
||||
#region Instrumentation
|
||||
if (LOG.IsDebugEnabled)
|
||||
{
|
||||
Expect.Call<HttpStatusCode>(response.StatusCode).Return(HttpStatusCode.OK);
|
||||
Expect.Call<string>(response.StatusDescription).Return("OK");
|
||||
}
|
||||
#endregion
|
||||
Expect.Call(response.Close);
|
||||
Expect.Call<bool>(request.HaveResponse).Return(true);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
125
test/Spring/Spring.Http.Tests/Spring.Http.Tests.2008.csproj
Normal file
125
test/Spring/Spring.Http.Tests/Spring.Http.Tests.2008.csproj
Normal file
@@ -0,0 +1,125 @@
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
|
||||
<PropertyGroup>
|
||||
<ProjectType>Local</ProjectType>
|
||||
<ProductVersion>9.0.30729</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{F04CEE18-3897-A399-46BF-459437475B21}</ProjectGuid>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ApplicationIcon>
|
||||
</ApplicationIcon>
|
||||
<AssemblyKeyContainerName>
|
||||
</AssemblyKeyContainerName>
|
||||
<AssemblyName>Spring.Http.Tests</AssemblyName>
|
||||
<AssemblyOriginatorKeyFile>
|
||||
</AssemblyOriginatorKeyFile>
|
||||
<DefaultClientScript>JScript</DefaultClientScript>
|
||||
<DefaultHTMLPageLayout>Grid</DefaultHTMLPageLayout>
|
||||
<DefaultTargetSchema>IE50</DefaultTargetSchema>
|
||||
<DelaySign>false</DelaySign>
|
||||
<OutputType>Library</OutputType>
|
||||
<RootNamespace>Spring</RootNamespace>
|
||||
<RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
|
||||
<StartupObject>
|
||||
</StartupObject>
|
||||
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<OutputPath>..\..\..\build\VS.Net.2008\Spring.Http.Tests\Debug\</OutputPath>
|
||||
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
|
||||
<BaseAddress>285212672</BaseAddress>
|
||||
<CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
|
||||
<ConfigurationOverrideFile>
|
||||
</ConfigurationOverrideFile>
|
||||
<DefineConstants>TRACE;DEBUG;NET_2_0;NET_3_0;NET_3_5</DefineConstants>
|
||||
<DocumentationFile>
|
||||
</DocumentationFile>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<FileAlignment>4096</FileAlignment>
|
||||
<NoStdLib>false</NoStdLib>
|
||||
<NoWarn>
|
||||
</NoWarn>
|
||||
<Optimize>false</Optimize>
|
||||
<RegisterForComInterop>false</RegisterForComInterop>
|
||||
<RemoveIntegerChecks>false</RemoveIntegerChecks>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<DebugType>full</DebugType>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<UseVSHostingProcess>true</UseVSHostingProcess>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<OutputPath>..\..\..\build\VS.Net.2008\Spring.Http.Tests\Release\</OutputPath>
|
||||
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
|
||||
<BaseAddress>285212672</BaseAddress>
|
||||
<CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
|
||||
<ConfigurationOverrideFile>
|
||||
</ConfigurationOverrideFile>
|
||||
<DefineConstants>TRACE;NET_2_0;NET_3_0;NET_3_5</DefineConstants>
|
||||
<DocumentationFile>
|
||||
</DocumentationFile>
|
||||
<DebugSymbols>false</DebugSymbols>
|
||||
<FileAlignment>4096</FileAlignment>
|
||||
<NoStdLib>false</NoStdLib>
|
||||
<NoWarn>
|
||||
</NoWarn>
|
||||
<Optimize>true</Optimize>
|
||||
<RegisterForComInterop>false</RegisterForComInterop>
|
||||
<RemoveIntegerChecks>false</RemoveIntegerChecks>
|
||||
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<DebugType>none</DebugType>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Common.Logging, Version=1.2.0.0, Culture=neutral, PublicKeyToken=af08829b84f0328e">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\lib\Net\2.0\Common.Logging.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="nunit.framework">
|
||||
<Name>nunit.framework</Name>
|
||||
<HintPath>..\..\..\lib\Net\2.0\nunit.framework.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Rhino.Mocks, Version=3.4.0.0, Culture=neutral, PublicKeyToken=0b3305902db7183f, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\lib\Net\2.0\Rhino.Mocks.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System">
|
||||
<Name>System</Name>
|
||||
</Reference>
|
||||
<Reference Include="System.XML" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="AssemblyInfo.cs" />
|
||||
<Compile Include="Http\Converters\ByteArrayHttpMessageConverterTests.cs" />
|
||||
<Compile Include="Http\Converters\StringHttpMessageConverterTests.cs" />
|
||||
<Compile Include="Http\Converters\Xml\DataContractHttpMessageConverterIntegrationTests.cs" />
|
||||
<Compile Include="Http\Converters\Xml\DataContractHttpMessageConverterTests.cs" />
|
||||
<Compile Include="Http\Converters\Xml\XmlDocumentHttpMessageConverterTests.cs" />
|
||||
<Compile Include="Http\MediaTypeTests.cs" />
|
||||
<Compile Include="Http\Rest\RestTemplateIntegrationTests.cs" />
|
||||
<Compile Include="Util\UriTemplateTests.cs" />
|
||||
<Compile Include="Http\Rest\RestTemplateTests.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\src\Spring\Spring.Core\Spring.Core.2008.csproj">
|
||||
<Project>{710961A3-0DF4-49E4-A26E-F5B9C044AC84}</Project>
|
||||
<Name>Spring.Core.2008</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\src\Spring\Spring.Http\Spring.Http.2008.csproj">
|
||||
<Project>{FAC04F79-4B1F-1D13-B30F-00EE04EC0FBC}</Project>
|
||||
<Name>Spring.Http.2008</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Spring.Http.Tests.dll.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PreBuildEvent>
|
||||
</PreBuildEvent>
|
||||
<PostBuildEvent>echo "Copying .xml files for tests"
|
||||
xcopy "$(ProjectDir)Data" ..\..\..\..\build\VS.Net.2008\Spring.Http.Tests\$(ConfigurationName)\ /y /s /q /d
|
||||
xcopy "$(ProjectDir)$(TargetFileName).config" ..\..\..\..\build\VS.Net.2008\Spring.Http.Tests\$(ConfigurationName)\ /y /s /q</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
151
test/Spring/Spring.Http.Tests/Spring.Http.Tests.2010.csproj
Normal file
151
test/Spring/Spring.Http.Tests/Spring.Http.Tests.2010.csproj
Normal file
@@ -0,0 +1,151 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
|
||||
<PropertyGroup>
|
||||
<ProjectType>Local</ProjectType>
|
||||
<ProductVersion>9.0.30729</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{4594CEE7-3897-A3BF-9946-5B4374F01821}</ProjectGuid>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ApplicationIcon>
|
||||
</ApplicationIcon>
|
||||
<AssemblyKeyContainerName>
|
||||
</AssemblyKeyContainerName>
|
||||
<AssemblyName>Spring.Http.Tests</AssemblyName>
|
||||
<AssemblyOriginatorKeyFile>
|
||||
</AssemblyOriginatorKeyFile>
|
||||
<DefaultClientScript>JScript</DefaultClientScript>
|
||||
<DefaultHTMLPageLayout>Grid</DefaultHTMLPageLayout>
|
||||
<DefaultTargetSchema>IE50</DefaultTargetSchema>
|
||||
<DelaySign>false</DelaySign>
|
||||
<OutputType>Library</OutputType>
|
||||
<RootNamespace>Spring</RootNamespace>
|
||||
<RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
|
||||
<StartupObject>
|
||||
</StartupObject>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<FileUpgradeFlags>
|
||||
</FileUpgradeFlags>
|
||||
<OldToolsVersion>3.5</OldToolsVersion>
|
||||
<UpgradeBackupLocation />
|
||||
<TargetFrameworkProfile />
|
||||
<PublishUrl>publish\</PublishUrl>
|
||||
<Install>true</Install>
|
||||
<InstallFrom>Disk</InstallFrom>
|
||||
<UpdateEnabled>false</UpdateEnabled>
|
||||
<UpdateMode>Foreground</UpdateMode>
|
||||
<UpdateInterval>7</UpdateInterval>
|
||||
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
|
||||
<UpdatePeriodically>false</UpdatePeriodically>
|
||||
<UpdateRequired>false</UpdateRequired>
|
||||
<MapFileExtensions>true</MapFileExtensions>
|
||||
<ApplicationRevision>0</ApplicationRevision>
|
||||
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
|
||||
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||
<UseApplicationTrust>false</UseApplicationTrust>
|
||||
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<OutputPath>..\..\..\build\VS.Net.2010\Spring.Http.Tests\Debug\</OutputPath>
|
||||
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
|
||||
<BaseAddress>285212672</BaseAddress>
|
||||
<CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
|
||||
<ConfigurationOverrideFile>
|
||||
</ConfigurationOverrideFile>
|
||||
<DefineConstants>TRACE;DEBUG;NET_2_0;NET_3_0;NET_3_5;NET_4_0</DefineConstants>
|
||||
<DocumentationFile>
|
||||
</DocumentationFile>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<FileAlignment>4096</FileAlignment>
|
||||
<NoStdLib>false</NoStdLib>
|
||||
<NoWarn>
|
||||
</NoWarn>
|
||||
<Optimize>false</Optimize>
|
||||
<RegisterForComInterop>false</RegisterForComInterop>
|
||||
<RemoveIntegerChecks>false</RemoveIntegerChecks>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<DebugType>full</DebugType>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<UseVSHostingProcess>true</UseVSHostingProcess>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<OutputPath>..\..\..\build\VS.Net.2010\Spring.Http.Tests\Release\</OutputPath>
|
||||
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
|
||||
<BaseAddress>285212672</BaseAddress>
|
||||
<CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
|
||||
<ConfigurationOverrideFile>
|
||||
</ConfigurationOverrideFile>
|
||||
<DefineConstants>TRACE;NET_2_0;NET_3_0;NET_3_5</DefineConstants>
|
||||
<DocumentationFile>
|
||||
</DocumentationFile>
|
||||
<DebugSymbols>false</DebugSymbols>
|
||||
<FileAlignment>4096</FileAlignment>
|
||||
<NoStdLib>false</NoStdLib>
|
||||
<NoWarn>
|
||||
</NoWarn>
|
||||
<Optimize>true</Optimize>
|
||||
<RegisterForComInterop>false</RegisterForComInterop>
|
||||
<RemoveIntegerChecks>false</RemoveIntegerChecks>
|
||||
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<DebugType>none</DebugType>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Common.Logging, Version=1.2.0.0, Culture=neutral, PublicKeyToken=af08829b84f0328e">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\lib\Net\2.0\Common.Logging.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="nunit.framework">
|
||||
<Name>nunit.framework</Name>
|
||||
<HintPath>..\..\..\lib\Net\2.0\nunit.framework.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Rhino.Mocks, Version=3.4.0.0, Culture=neutral, PublicKeyToken=0b3305902db7183f, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\lib\Net\2.0\Rhino.Mocks.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System">
|
||||
<Name>System</Name>
|
||||
</Reference>
|
||||
<Reference Include="System.Runtime.Serialization" />
|
||||
<Reference Include="System.ServiceModel" />
|
||||
<Reference Include="System.ServiceModel.Web" />
|
||||
<Reference Include="System.XML" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="AssemblyInfo.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Http\Converters\ByteArrayHttpMessageConverterTests.cs" />
|
||||
<Compile Include="Http\Converters\StringHttpMessageConverterTests.cs" />
|
||||
<Compile Include="Http\Converters\Xml\DataContractHttpMessageConverterTests.cs" />
|
||||
<Compile Include="Http\Converters\Xml\DataContractHttpMessageConverterIntegrationTests.cs" />
|
||||
<Compile Include="Http\Converters\Xml\XmlDocumentHttpMessageConverterTests.cs" />
|
||||
<Compile Include="Http\MediaTypeTests.cs" />
|
||||
<Compile Include="Http\Rest\RestTemplateIntegrationTests.cs" />
|
||||
<Compile Include="Http\Rest\RestTemplateTests.cs" />
|
||||
<Compile Include="Util\UriTemplateTests.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\src\Spring\Spring.Core\Spring.Core.2010.csproj">
|
||||
<Project>{710961A3-0DF4-49E4-A26E-F5B9C044AC84}</Project>
|
||||
<Name>Spring.Core.2010</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\src\Spring\Spring.Http\Spring.Http.2010.csproj">
|
||||
<Project>{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</Project>
|
||||
<Name>Spring.Http.2010</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Spring.Http.Tests.dll.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PreBuildEvent>
|
||||
</PreBuildEvent>
|
||||
<PostBuildEvent>echo "Copying .xml files for tests"
|
||||
xcopy "$(ProjectDir)Data" ..\..\..\..\build\VS.Net.2010\Spring.Http.Tests\$(ConfigurationName)\ /y /s /q /d
|
||||
xcopy "$(ProjectDir)$(TargetFileName).config" ..\..\..\..\build\VS.Net.2010\Spring.Http.Tests\$(ConfigurationName)\ /y /s /q</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
18
test/Spring/Spring.Http.Tests/Spring.Http.Tests.dll.config
Normal file
18
test/Spring/Spring.Http.Tests/Spring.Http.Tests.dll.config
Normal file
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
|
||||
<configSections>
|
||||
<sectionGroup name="common">
|
||||
<section name="logging" type="Common.Logging.ConfigurationSectionHandler, Common.Logging" />
|
||||
</sectionGroup>
|
||||
</configSections>
|
||||
|
||||
<common>
|
||||
<logging>
|
||||
<factoryAdapter type="Common.Logging.Simple.TraceLoggerFactoryAdapter, Common.Logging">
|
||||
<arg key="level" value="ALL" />
|
||||
</factoryAdapter>
|
||||
</logging>
|
||||
</common>
|
||||
|
||||
</configuration>
|
||||
227
test/Spring/Spring.Http.Tests/Util/UriTemplateTests.cs
Normal file
227
test/Spring/Spring.Http.Tests/Util/UriTemplateTests.cs
Normal file
@@ -0,0 +1,227 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Spring.Util
|
||||
{
|
||||
/// <summary>
|
||||
/// Unit tests for the UriTemplate class.
|
||||
/// </summary>
|
||||
/// <author>Arjen Poutsma</author>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <author>Bruno Baia (.NET)</author>
|
||||
[TestFixture]
|
||||
public class UriTemplateTests
|
||||
{
|
||||
[Test]
|
||||
public void GetVariableNames()
|
||||
{
|
||||
UriTemplate template = new UriTemplate("http://example.com/hotels/{hotel}/bookings/{booking}");
|
||||
string[] variableNames = template.VariableNames;
|
||||
Assert.AreEqual(new string[] { "hotel", "booking" }, variableNames, "Invalid variable names");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ExpandVarArgs()
|
||||
{
|
||||
// absolute
|
||||
UriTemplate template = new UriTemplate("http://example.com/hotels/{hotel}/bookings/{booking}");
|
||||
Uri result = template.Expand("1", "42");
|
||||
Assert.AreEqual(new Uri("http://example.com/hotels/1/bookings/42"), result, "Invalid expanded template");
|
||||
|
||||
// relative
|
||||
template = new UriTemplate("/hotels/{hotel}/bookings/{booking}");
|
||||
result = template.Expand("1", "42");
|
||||
Assert.AreEqual(new Uri("/hotels/1/bookings/42", UriKind.Relative), result, "Invalid expanded template");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MultipleExpandVarArgs()
|
||||
{
|
||||
UriTemplate template = new UriTemplate("http://example.com/hotels/{hotel}/bookings/{booking}");
|
||||
Uri result = template.Expand("2", "21");
|
||||
result = template.Expand("1", "42");
|
||||
Assert.AreEqual(new Uri("http://example.com/hotels/1/bookings/42"), result, "Invalid expanded template");
|
||||
}
|
||||
|
||||
[Test]
|
||||
[ExpectedException(
|
||||
typeof(ArgumentException),
|
||||
ExpectedMessage = "Invalid amount of variables values in 'http://example.com/hotels/{hotel}/bookings/{booking}': expected 2; got 3")]
|
||||
public void ExpandVarArgsInvalidAmountVariables()
|
||||
{
|
||||
UriTemplate template = new UriTemplate("http://example.com/hotels/{hotel}/bookings/{booking}");
|
||||
template.Expand("1", "42", "100");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ExpandVarArgsDuplicateVariables()
|
||||
{
|
||||
UriTemplate template = new UriTemplate("http://example.com/order/{c}/{c}/{c}");
|
||||
Assert.AreEqual(new string[] { "c" }, template.VariableNames, "Invalid variable names");
|
||||
Uri result = template.Expand("cheeseburger");
|
||||
Assert.AreEqual(new Uri("http://example.com/order/cheeseburger/cheeseburger/cheeseburger"), result, "Invalid expanded template");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ExpandDictionary()
|
||||
{
|
||||
IDictionary<string, string> uriVariables = new Dictionary<String, String>(2);
|
||||
uriVariables.Add("booking", "42");
|
||||
uriVariables.Add("hotel", "1");
|
||||
|
||||
// absolute
|
||||
UriTemplate template = new UriTemplate("http://example.com/hotels/{hotel}/bookings/{booking}");
|
||||
Uri result = template.Expand(uriVariables);
|
||||
Assert.AreEqual(new Uri("http://example.com/hotels/1/bookings/42"), result, "Invalid expanded template");
|
||||
|
||||
// relative
|
||||
template = new UriTemplate("hotels/{hotel}/bookings/{booking}");
|
||||
result = template.Expand(uriVariables);
|
||||
Assert.AreEqual(new Uri("hotels/1/bookings/42", UriKind.Relative), result, "Invalid expanded template");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MultipleExpandDictionary()
|
||||
{
|
||||
UriTemplate template = new UriTemplate("http://example.com/hotels/{hotel}/bookings/{booking}");
|
||||
|
||||
IDictionary<string, string> uriVariables = new Dictionary<String, String>(2);
|
||||
uriVariables.Add("booking", "21");
|
||||
uriVariables.Add("hotel", "2");
|
||||
Uri result = template.Expand(uriVariables);
|
||||
|
||||
uriVariables = new Dictionary<String, String>(2);
|
||||
uriVariables.Add("booking", "42");
|
||||
uriVariables.Add("hotel", "1");
|
||||
result = template.Expand(uriVariables);
|
||||
|
||||
Assert.AreEqual(new Uri("http://example.com/hotels/1/bookings/42"), result, "Invalid expanded template");
|
||||
}
|
||||
|
||||
[Test]
|
||||
[ExpectedException(
|
||||
typeof(ArgumentException),
|
||||
ExpectedMessage = "Invalid amount of variables values in 'http://example.com/hotels/{hotel}/bookings/{booking}': expected 2; got 1")]
|
||||
public void ExpandDictionaryInvalidAmountVariables()
|
||||
{
|
||||
IDictionary<string, string> uriVariables = new Dictionary<String, String>(2);
|
||||
uriVariables.Add("hotel", "1");
|
||||
|
||||
UriTemplate template = new UriTemplate("http://example.com/hotels/{hotel}/bookings/{booking}");
|
||||
template.Expand(uriVariables);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[ExpectedException(
|
||||
typeof(ArgumentException),
|
||||
ExpectedMessage = "'uriVariables' dictionary has no value for 'hotel'")]
|
||||
public void ExpandDictionaryUnboundVariables()
|
||||
{
|
||||
IDictionary<string, string> uriVariables = new Dictionary<String, String>(2);
|
||||
uriVariables.Add("booking", "42");
|
||||
uriVariables.Add("bar", "1");
|
||||
|
||||
UriTemplate template = new UriTemplate("http://example.com/hotels/{hotel}/bookings/{booking}");
|
||||
template.Expand(uriVariables);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ExpandEncoded()
|
||||
{
|
||||
UriTemplate template = new UriTemplate("http://example.com/hotel list/{hotel}");
|
||||
Uri result = template.Expand("Z\u00fcrich");
|
||||
Assert.AreEqual(new Uri("http://example.com/hotel%20list/Z%C3%BCrich"), result, "Invalid expanded template");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Matches()
|
||||
{
|
||||
UriTemplate template = new UriTemplate("http://example.com/hotels/{hotel}/bookings/{booking}/");
|
||||
Assert.IsTrue(template.Matches("http://example.com/hotels/1/bookings/42/"), "UriTemplate does not match");
|
||||
Assert.IsFalse(template.Matches("hhhhttp://example.com/hotels/1/bookings/42/"), "UriTemplate matches");
|
||||
Assert.IsFalse(template.Matches("http://example.com/hotels/1/bookings/42/blabla"), "UriTemplate matches");
|
||||
Assert.IsFalse(template.Matches("http://example.com/hotels/bookings/"), "UriTemplate matches");
|
||||
Assert.IsFalse(template.Matches(""), "UriTemplate matches");
|
||||
Assert.IsFalse(template.Matches(null), "UriTemplate matches");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Match()
|
||||
{
|
||||
UriTemplate template = new UriTemplate("http://example.com/hotels/{hotel}/bookings/{booking}");
|
||||
IDictionary<string, string> result = template.Match("http://example.com/hotels/1/bookings/42");
|
||||
Assert.AreEqual(2, result.Count);
|
||||
Assert.AreEqual("1", result["hotel"]);
|
||||
Assert.AreEqual("42", result["booking"]);
|
||||
|
||||
result = template.Match("http://example.com/hotels/1/bookings");
|
||||
Assert.AreEqual(0, result.Count);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void matchDuplicate()
|
||||
{
|
||||
UriTemplate template = new UriTemplate("/order/{c}/{c}/{c}");
|
||||
IDictionary<string, string> result = template.Match("/order/cheeseburger/cheeseburger/cheeseburger");
|
||||
Assert.AreEqual(1, result.Count);
|
||||
Assert.AreEqual("cheeseburger", result["c"]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MatchMultipleInOneSegment()
|
||||
{
|
||||
UriTemplate template = new UriTemplate("/{foo}-{bar}");
|
||||
IDictionary<string, string> result = template.Match("/12-34");
|
||||
Assert.AreEqual(2, result.Count);
|
||||
Assert.AreEqual("12", result["foo"]);
|
||||
Assert.AreEqual("34", result["bar"]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MatchesQueryVariables()
|
||||
{
|
||||
UriTemplate template = new UriTemplate("/search?q={query}");
|
||||
Assert.IsTrue(template.Matches("/search?q=foo"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MatchesFragments()
|
||||
{
|
||||
UriTemplate template = new UriTemplate("/search#{fragment}");
|
||||
Assert.IsTrue(template.Matches("/search#foo"));
|
||||
|
||||
template = new UriTemplate("/search?query={query}#{fragment}");
|
||||
Assert.IsTrue(template.Matches("/search?query=foo#bar"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ExpandWithAtSign()
|
||||
{
|
||||
UriTemplate template = new UriTemplate("http://localhost/query={query}");
|
||||
Uri uri = template.Expand("foo@bar");
|
||||
Assert.AreEqual("http://localhost/query=foo@bar", uri.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user