├── .gitignore ├── .travis.yml ├── .vscode ├── c_cpp_properties.json ├── launch.json ├── settings.json └── tasks.json ├── BuildScriptUnix.sh ├── BuildScriptWindows.ps1 ├── CMakeLists.txt ├── HttpClient.geany ├── PullAndBuildWindows.bat ├── README.md ├── build_stuff ├── WindowsAdditions │ └── Invoke-MsBuild.psm1 └── cpplint │ ├── GetLatestCPPLint.sh │ └── cpplint.py ├── makefile └── source ├── HttpClient.cpp ├── HttpClient.h ├── HttpResponse.cpp ├── HttpResponse.h ├── Log.cpp ├── Log.h ├── StringBufferHelper.cpp ├── StringBufferHelper.h ├── TCPClient.cpp ├── TCPClient.h ├── URL.cpp ├── URL.h ├── main.cpp └── tests ├── CMakeLists.txt ├── CallTests.cpp ├── GetLatestCatch.sh ├── URLTests ├── URLTests.cpp └── catch.hpp /.gitignore: -------------------------------------------------------------------------------- 1 | # Escaped folders 2 | bin 3 | objects 4 | build 5 | 6 | # Compiled Object files 7 | *.slo 8 | *.lo 9 | *.o 10 | *.obj 11 | 12 | # Precompiled Headers 13 | *.gch 14 | *.pch 15 | 16 | # Compiled Dynamic libraries 17 | *.so 18 | *.dylib 19 | *.dll 20 | 21 | # Fortran module files 22 | *.mod 23 | 24 | # Compiled Static libraries 25 | *.lai 26 | *.la 27 | *.a 28 | *.lib 29 | 30 | # Executables 31 | *.exe 32 | *.out 33 | *.app 34 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | compiler: 3 | #- gcc 4 | - clang 5 | # Change this to your needs 6 | #before_script: 7 | # - cd build 8 | script: ./BuildScriptUnix.sh -------------------------------------------------------------------------------- /.vscode/c_cpp_properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "name": "Mac", 5 | "includePath": [ 6 | "/usr/local/include", 7 | "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1", 8 | "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/10.0.1/include", 9 | "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include", 10 | "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/usr/include", 11 | "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/System/Library/Frameworks", 12 | "${workspaceFolder}" 13 | ], 14 | "defines": [], 15 | "macFrameworkPath": [], 16 | "compilerPath": "/usr/local/bin/gcc-7", 17 | "cStandard": "c11", 18 | "cppStandard": "c++17", 19 | "intelliSenseMode": "clang-x64" 20 | } 21 | ], 22 | "version": 4 23 | } -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "C++ Launch", 6 | "type": "cppdbg", 7 | "request": "launch", 8 | "targetArchitecture": "x64", 9 | "program": "${workspaceRoot}/build/HttpClient", 10 | "args": ["www.example.com"], 11 | "stopAtEntry": false, 12 | "cwd": "${workspaceRoot}", 13 | "environment": [], 14 | "externalConsole": false, 15 | "linux": { 16 | "MIMode": "gdb" 17 | }, 18 | "osx": { 19 | "MIMode": "lldb" 20 | }, 21 | "windows": { 22 | "MIMode": "gdb" 23 | } 24 | }, 25 | { 26 | "name": "C++ Attach", 27 | "type": "cppdbg", 28 | "request": "launch", 29 | "targetArchitecture": "x64", 30 | "program": "${workspaceRoot}/build/source/tests/HttpClientTests", 31 | "args": [], 32 | "stopAtEntry": false, 33 | "cwd": "${workspaceRoot}", 34 | "environment": [], 35 | "processId": "${command.pickProcess}", 36 | "externalConsole": false, 37 | "linux": { 38 | "MIMode": "gdb" 39 | }, 40 | "osx": { 41 | "MIMode": "lldb" 42 | }, 43 | "windows": { 44 | "MIMode": "gdb" 45 | } 46 | } 47 | ] 48 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "iosfwd": "cpp", 4 | "__config": "cpp", 5 | "__nullptr": "cpp", 6 | "cstddef": "cpp", 7 | "exception": "cpp", 8 | "limits": "cpp", 9 | "typeinfo": "cpp", 10 | "*.tcc": "cpp", 11 | "cctype": "cpp", 12 | "clocale": "cpp", 13 | "cmath": "cpp", 14 | "cstdint": "cpp", 15 | "cstdio": "cpp", 16 | "cstdlib": "cpp", 17 | "cwchar": "cpp", 18 | "type_traits": "cpp", 19 | "initializer_list": "cpp", 20 | "new": "cpp", 21 | "string_view": "cpp" 22 | } 23 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "0.1.0", 5 | "osx":{ 6 | "command": "bash", 7 | "args": [ 8 | "-c" 9 | ], 10 | "isShellCommand": true, 11 | "showOutput": "always", 12 | "suppressTaskName": true, 13 | "tasks": [ 14 | { 15 | "taskName": "Build", 16 | "suppressTaskName": true, 17 | "args": [ 18 | "./BuildScriptUnix.sh" 19 | ], 20 | "isBuildCommand": true 21 | } 22 | ] 23 | } 24 | } -------------------------------------------------------------------------------- /BuildScriptUnix.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # declare STRING variable 3 | echo "Creating native make..." 4 | if [ ! -d "build" ]; then 5 | mkdir build 6 | fi 7 | 8 | cd build 9 | 10 | cmake -G "Unix Makefiles" .. && \ 11 | 12 | echo "Running native make" && \ 13 | make && \ 14 | 15 | echo "Running make test" && \ 16 | ctest --verbose && \ 17 | 18 | echo "Running CppLint" && \ 19 | python ../build_stuff/cpplint/cpplint.py ../source/*.* 20 | 21 | if [ $? -eq 0 ]; then 22 | echo "Build and lint succeded" 23 | else 24 | printf "\033[1;31mBuild or lint failed, no copy to the bin folder will be made\033[0m\n" 25 | exit 1 26 | fi 27 | 28 | cd .. 29 | 30 | if [ ! -d "bin" ]; then 31 | mkdir bin 32 | fi 33 | 34 | echo "Copying the executable to the bin folder" 35 | cp build/HttpClient bin/HttpClient 36 | 37 | -------------------------------------------------------------------------------- /BuildScriptWindows.ps1: -------------------------------------------------------------------------------- 1 | C:\Chocolatey\bin\cmake.bat "Visual Studio 11 2012" .. 2 | Import-Module -Name ".\build_stuff\WindowsAdditions\Invoke-MsBuild.psm1" 3 | 4 | Write-Host("Starting build") 5 | $buildSucceeded = Invoke-MsBuild -Path ".\HttpClient.sln" 6 | 7 | if ($buildSucceeded) 8 | { Write-Host "Build completed successfully." } 9 | else 10 | { Write-Host "Build failed. Check the build log file for errors." } -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 2.6) 2 | project (HttpClient) 3 | set(source_dir source/) 4 | #set(CMAKE_BINARY_DIR "${PROJECT_SOURCE_DIR}/bin") 5 | #set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) 6 | #set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) 7 | #set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) 8 | set(source_files ${source_dir}main.cpp source/HttpClient.cpp ${source_dir}HttpResponse.cpp ${source_dir}TCPClient.cpp ${source_dir}StringBufferHelper.cpp ${source_dir}URL.cpp ${source_dir}Log.cpp) 9 | add_executable(HttpClient ${source_files}) 10 | add_definitions(-std=c++11) 11 | include_directories(.) 12 | 13 | if(WIN32) 14 | target_link_libraries(HttpClient ws2_32) 15 | else() 16 | endif() 17 | 18 | enable_testing(true) 19 | add_subdirectory(${source_dir}tests) 20 | #add_subdirectory(${CMAKE_BINARY_DIR}) 21 | #include_directories(tests) -------------------------------------------------------------------------------- /HttpClient.geany: -------------------------------------------------------------------------------- 1 | [file_prefs] 2 | final_new_line=true 3 | ensure_convert_new_lines=false 4 | strip_trailing_spaces=false 5 | replace_tabs=false 6 | 7 | [indentation] 8 | indent_width=2 9 | indent_type=0 10 | indent_hard_tab_width=8 11 | detect_indent=false 12 | detect_indent_width=false 13 | indent_mode=2 14 | 15 | [project] 16 | name=HttpClient 17 | base_path=/home/emil/Source/HttpClient 18 | description= 19 | file_patterns=*.cpp;*.h; 20 | 21 | [long line marker] 22 | long_line_behaviour=1 23 | long_line_column=72 24 | 25 | [files] 26 | current_page=0 27 | FILE_NAME_0=42;C++;0;EUTF-8;1;1;0;%2Fhome%2Femil%2FSource%2FHttpClient%2Fsource%2FHttpClient.cpp;0;4 28 | FILE_NAME_1=154;Sh;0;EUTF-8;1;1;0;%2Fhome%2Femil%2FSource%2FHttpClient%2Fbuild%2FBuildScriptUnix.sh;0;4 29 | FILE_NAME_2=25;C;0;EUTF-8;1;1;0;%2Fhome%2Femil%2FSource%2FHttpClient%2Fsource%2FURL.h;0;4 30 | FILE_NAME_3=550;CMake;0;EUTF-8;0;1;0;%2Fhome%2Femil%2FSource%2FHttpClient%2FCMakeLists.txt;0;4 31 | FILE_NAME_4=1517;C++;0;EUTF-8;0;1;0;%2Fhome%2Femil%2FSource%2FHttpClient%2Fsource%2FURL.cpp;0;4 32 | FILE_NAME_5=159;C;0;EUTF-8;0;1;0;%2Fhome%2Femil%2FSource%2FHttpClient%2Fsource%2FHttpClient.h;0;4 33 | FILE_NAME_6=52;C++;0;EUTF-8;0;1;0;%2Fhome%2Femil%2FSource%2FHttpClient%2Fsource%2FHttpResponse.cpp;0;4 34 | FILE_NAME_7=89;C;0;EUTF-8;0;1;0;%2Fhome%2Femil%2FSource%2FHttpClient%2Fsource%2FHttpResponse.h;0;4 35 | FILE_NAME_8=24;C++;0;EUTF-8;0;1;0;%2Fhome%2Femil%2FSource%2FHttpClient%2Fsource%2FLog.cpp;0;4 36 | FILE_NAME_9=24;C;0;EUTF-8;0;1;0;%2Fhome%2Femil%2FSource%2FHttpClient%2Fsource%2FLog.h;0;4 37 | FILE_NAME_10=437;C++;0;EUTF-8;0;1;0;%2Fhome%2Femil%2FSource%2FHttpClient%2Fsource%2Fmain.cpp;0;4 38 | FILE_NAME_11=24;C++;0;EUTF-8;0;1;0;%2Fhome%2Femil%2FSource%2FHttpClient%2Fsource%2FStringBufferHelper.cpp;0;4 39 | FILE_NAME_12=329;C;0;EUTF-8;0;1;0;%2Fhome%2Femil%2FSource%2FHttpClient%2Fsource%2FStringBufferHelper.h;0;4 40 | FILE_NAME_13=6112;C++;0;EUTF-8;0;1;0;%2Fhome%2Femil%2FSource%2FHttpClient%2Fsource%2FTCPClient.cpp;0;4 41 | FILE_NAME_14=23;C;0;EUTF-8;0;1;0;%2Fhome%2Femil%2FSource%2FHttpClient%2Fsource%2FTCPClient.h;0;4 42 | 43 | [VTE] 44 | last_dir=/home/emil/Source/ConsoleApp1 45 | 46 | [build-menu] 47 | CMakeFT_00_LB=ByggProjekt 48 | CMakeFT_00_CM=./BuildScriptUnix.sh 49 | CMakeFT_00_WD=/home/emil/Source/HttpClient/build 50 | filetypes=CMake;C++; 51 | NF_00_LB=_Make 52 | NF_00_CM=%d/../build/BuildScriptUnix.sh 53 | NF_00_WD=%d/../build 54 | NF_03_LB= 55 | NF_03_CM= 56 | NF_03_WD= 57 | C++FT_01_LB=Bygg 58 | C++FT_01_CM= 59 | C++FT_01_WD= 60 | EX_00_LB=_Exekvera 61 | EX_00_CM= 62 | EX_00_WD= 63 | -------------------------------------------------------------------------------- /PullAndBuildWindows.bat: -------------------------------------------------------------------------------- 1 | git pull 2 | cd build 3 | BuildScriptWindows.ps1 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HttpClient([![Build Status](https://travis-ci.org/emilw/HttpClient.svg?branch=master)](https://travis-ci.org/emilw/HttpClient)) 2 | ========== 3 | A cross platform HTTP client written in C++ based on raw sockets 4 | 5 | ## Get started 6 | #### Get started Linux/Mac Os X 7 | - Make sure you have CMake installed 8 | - Git Clone the library 9 | - Go to the project root folder 10 | - cd build 11 | - run ./BuildScriptUnix.sh 12 | 13 | #### Get started Windows 14 | - Make sure you have Chocolate package distributor installed 15 | - Retrieve CMake that way(The build script is dependent on that path) 16 | - Run Git Clone to get the project locally 17 | - Go to the project root folder 18 | - Run the PullAndBuildWindows.bat script 19 | 20 | 21 | ## Todo 22 | - Make sure that all code is aligned to CppLint so it's possible to turn that check on when running the Travis builds. 23 | - Add the Catch library for UnitTesting 24 | - Support for SSL, using Open SSL 25 | - Automatic builds for Windows, might be local seems impossible to find free windows build servers 26 | -------------------------------------------------------------------------------- /build_stuff/WindowsAdditions/Invoke-MsBuild.psm1: -------------------------------------------------------------------------------- 1 | #Requires -Version 2.0 2 | function Invoke-MsBuild 3 | { 4 | <# 5 | .SYNOPSIS 6 | Builds the given Visual Studio solution or project file using MSBuild. 7 | 8 | .DESCRIPTION 9 | Executes the MSBuild.exe tool against the specified Visual Studio solution or project file. 10 | Returns true if the build succeeded, false if the build failed, and null if we could not determine the build result. 11 | If using the PathThru switch, the process running MSBuild is returned instead. 12 | 13 | .PARAMETER Path 14 | The path of the Visual Studio solution or project to build (e.g. a .sln or .csproj file). 15 | 16 | .PARAMETER MsBuildParameters 17 | Additional parameters to pass to the MsBuild command-line tool. This can be any valid MsBuild command-line parameters except for the path of 18 | the solution/project to build. 19 | 20 | See http://msdn.microsoft.com/en-ca/library/vstudio/ms164311.aspx for valid MsBuild command-line parameters. 21 | 22 | .PARAMETER $BuildLogDirectoryPath 23 | The directory path to write the build log file to. 24 | Defaults to putting the log file in the users temp directory (e.g. C:\Users\[User Name]\AppData\Local\Temp). 25 | Use the keyword "PathDirectory" to put the log file in the same directory as the .sln or project file being built. 26 | 27 | .PARAMETER AutoLaunchBuildLog 28 | If set, this switch will cause the build log to automatically be launched into the default viewer if the build fails. 29 | NOTE: This switch cannot be used with the PassThru switch. 30 | 31 | .PARAMETER KeepBuildLogOnSuccessfulBuilds 32 | If set, this switch will cause the msbuild log file to not be deleted on successful builds; normally it is only kept around on failed builds. 33 | NOTE: This switch cannot be used with the PassThru switch. 34 | 35 | .PARAMETER ShowBuildWindow 36 | If set, this switch will cause a command prompt window to be shown in order to view the progress of the build. 37 | 38 | .PARAMETER ShowBuildWindowAndPromptForInputBeforeClosing 39 | If set, this switch will cause a command prompt window to be shown in order to view the progress of the build, and it will remain open 40 | after the build completes until the user presses a key on it. 41 | NOTE: If not using PassThru, the user will need to provide input before execution will return back to the calling script. 42 | 43 | .PARAMETER PassThru 44 | If set, this switch will cause the script not to wait until the build (launched in another process) completes before continuing execution. 45 | Instead the build will be started in a new process and that process will immediately be returned, allowing the calling script to continue 46 | execution while the build is performed, and also to inspect the process to see when it completes. 47 | NOTE: This switch cannot be used with the AutoLaunchBuildLog or KeepBuildLogOnSuccessfulBuilds switches. 48 | 49 | .PARAMETER GetLogPath 50 | If set, the build will not actually be performed. 51 | Instead it will just return the full path of the MsBuild Log file that would be created if the build is performed with the same parameters. 52 | 53 | .OUTPUTS 54 | When the -PassThru switch is not provided, a boolean value is returned; $true indicates that MsBuild completed successfully, $false indicates 55 | that MsBuild failed with errors (or that something else went wrong), and $null indicates that we were unable to determine if the build succeeded or failed. 56 | 57 | When the -PassThru switch is provided, the process being used to run the build is returned. 58 | 59 | .EXAMPLE 60 | $buildSucceeded = Invoke-MsBuild -Path "C:\Some Folder\MySolution.sln" 61 | 62 | if ($buildSucceeded) 63 | { Write-Host "Build completed successfully." } 64 | else 65 | { Write-Host "Build failed. Check the build log file for errors." } 66 | 67 | Perform the default MSBuild actions on the Visual Studio solution to build the projects in it, and returns whether the build succeeded or failed. 68 | The PowerShell script will halt execution until MsBuild completes. 69 | 70 | .EXAMPLE 71 | $process = Invoke-MsBuild -Path "C:\Some Folder\MySolution.sln" -PassThru 72 | 73 | Perform the default MSBuild actions on the Visual Studio solution to build the projects in it. 74 | The PowerShell script will not halt execution; instead it will return the process performing MSBuild actions back to the caller while the action is performed. 75 | 76 | .EXAMPLE 77 | Invoke-MsBuild -Path "C:\Some Folder\MyProject.csproj" -MsBuildParameters "/target:Clean;Build" -ShowBuildWindow 78 | 79 | Cleans then Builds the given C# project. 80 | A window displaying the output from MsBuild will be shown so the user can view the progress of the build. 81 | 82 | .EXAMPLE 83 | Invoke-MsBuild -Path "C:\MySolution.sln" -Params "/target:Clean;Build /property:Configuration=Release;Platform=x64;BuildInParallel=true /verbosity:Detailed /maxcpucount" 84 | 85 | Cleans then Builds the given solution, specifying to build the project in parallel in the Release configuration for the x64 platform. 86 | Here the shorter "Params" alias is used instead of the full "MsBuildParameters" parameter name. 87 | 88 | .EXAMPLE 89 | Invoke-MsBuild -Path "C:\Some Folder\MyProject.csproj" -ShowBuildWindowAndPromptForInputBeforeClosing -AutoLaunchBuildLog 90 | 91 | Builds the given C# project. 92 | A window displaying the output from MsBuild will be shown so the user can view the progress of the build, and it will not close until the user 93 | gives the window some input. This function will also not return until the user gives the window some input, halting the powershell script execution. 94 | If the build fails, the build log will automatically be opened in the default text viewer. 95 | 96 | .EXAMPLE 97 | Invoke-MsBuild -Path "C:\Some Folder\MyProject.csproj" -BuildLogDirectoryPath "C:\BuildLogs" -KeepBuildLogOnSuccessfulBuilds -AutoLaunchBuildLog 98 | 99 | Builds the given C# project. 100 | The build log will be saved in "C:\BuildLogs", and they will not be automatically deleted even if the build succeeds. 101 | If the build fails, the build log will automatically be opened in the default text viewer. 102 | 103 | .EXAMPLE 104 | Invoke-MsBuild -Path "C:\Some Folder\MyProject.csproj" -BuildLogDirectoryPath PathDirectory 105 | 106 | Builds the given C# project. 107 | The build log will be saved in "C:\Some Folder\", which is the same directory as the project being built (i.e. directory specified in the Path). 108 | 109 | .EXAMPLE 110 | Invoke-MsBuild -Path "C:\Database\Database.dbproj" -P "/t:Deploy /p:TargetDatabase=MyDatabase /p:TargetConnectionString=`"Data Source=DatabaseServerName`;Integrated Security=True`;Pooling=False`" /p:DeployToDatabase=True" 111 | 112 | Deploy the Visual Studio Database Project to the database "MyDatabase". 113 | Here the shorter "P" alias is used instead of the full "MsBuildParameters" parameter name. 114 | The shorter alias' of the msbuild parameters are also used; "/t" instead of "/target", and "/p" instead of "/property". 115 | 116 | .EXAMPLE 117 | Invoke-MsBuild -Path "C:\Some Folder\MyProject.csproj" -BuildLogDirectoryPath "C:\BuildLogs" -GetLogPath 118 | 119 | Returns the full path to the MsBuild Log file that would be created if the build was ran with the same parameters. 120 | In this example the returned log path might be "C:\BuildLogs\MyProject.msbuild.log". 121 | If the BuildLogDirectoryPath was not provided, the returned log path might be "C:\Some Folder\MyProject.msbuild.log". 122 | 123 | .LINK 124 | Project home: https://invokemsbuild.codeplex.com 125 | 126 | .NOTES 127 | Name: Invoke-MsBuild 128 | Author: Daniel Schroeder (originally based on the module at http://geekswithblogs.net/dwdii/archive/2011/05/27/part-2-automating-a-visual-studio-build-with-powershell.aspx) 129 | Version: 1.5 130 | #> 131 | [CmdletBinding(DefaultParameterSetName="Wait")] 132 | param 133 | ( 134 | [parameter(Position=0,Mandatory=$true,ValueFromPipeline=$true,HelpMessage="The path to the file to build with MsBuild (e.g. a .sln or .csproj file).")] 135 | [ValidateScript({Test-Path $_})] 136 | [string] $Path, 137 | 138 | [parameter(Mandatory=$false)] 139 | [Alias("Params")] 140 | [Alias("P")] 141 | [string] $MsBuildParameters, 142 | 143 | [parameter(Mandatory=$false)] 144 | [ValidateNotNullOrEmpty()] 145 | [Alias("L")] 146 | [string] $BuildLogDirectoryPath = $env:Temp, 147 | 148 | [parameter(Mandatory=$false,ParameterSetName="Wait")] 149 | [ValidateNotNullOrEmpty()] 150 | [Alias("AutoLaunch")] 151 | [Alias("A")] 152 | [switch] $AutoLaunchBuildLogOnFailure, 153 | 154 | [parameter(Mandatory=$false,ParameterSetName="Wait")] 155 | [ValidateNotNullOrEmpty()] 156 | [Alias("Keep")] 157 | [Alias("K")] 158 | [switch] $KeepBuildLogOnSuccessfulBuilds, 159 | 160 | [parameter(Mandatory=$false)] 161 | [Alias("Show")] 162 | [Alias("S")] 163 | [switch] $ShowBuildWindow, 164 | 165 | [parameter(Mandatory=$false)] 166 | [Alias("Prompt")] 167 | [switch] $ShowBuildWindowAndPromptForInputBeforeClosing, 168 | 169 | [parameter(Mandatory=$false,ParameterSetName="PassThru")] 170 | [switch] $PassThru, 171 | 172 | [parameter(Mandatory=$false)] 173 | [Alias("Get")] 174 | [Alias("G")] 175 | [switch] $GetLogPath 176 | ) 177 | 178 | BEGIN { } 179 | END { } 180 | PROCESS 181 | { 182 | # Turn on Strict Mode to help catch syntax-related errors. 183 | # This must come after a script's/function's param section. 184 | # Forces a function to be the first non-comment code to appear in a PowerShell Script/Module. 185 | Set-StrictMode -Version Latest 186 | 187 | # Default the ParameterSet variables that may not have been set depending on which parameter set is being used. This is required for PowerShell v2.0 compatibility. 188 | if (!(Test-Path Variable:Private:AutoLaunchBuildLogOnFailure)) { $AutoLaunchBuildLogOnFailure = $false } 189 | if (!(Test-Path Variable:Private:KeepBuildLogOnSuccessfulBuilds)) { $KeepBuildLogOnSuccessfulBuilds = $false } 190 | if (!(Test-Path Variable:Private:PassThru)) { $PassThru = $false } 191 | 192 | # If the keyword was supplied, place the log in the same folder as the solution/project being built. 193 | if ($BuildLogDirectoryPath.Equals("PathDirectory", [System.StringComparison]::InvariantCultureIgnoreCase)) 194 | { 195 | $BuildLogDirectoryPath = [System.IO.Path]::GetDirectoryName($Path) 196 | } 197 | 198 | # Store the VS Command Prompt to do the build in, if one exists. 199 | $vsCommandPrompt = Get-VisualStudioCommandPromptPath 200 | 201 | # Local Variables. 202 | $solutionFileName = (Get-ItemProperty -Path $Path).Name 203 | $buildLogFilePath = (Join-Path $BuildLogDirectoryPath $solutionFileName) + ".msbuild.log" 204 | $windowStyle = if ($ShowBuildWindow -or $ShowBuildWindowAndPromptForInputBeforeClosing) { "Normal" } else { "Hidden" } 205 | $buildCrashed = $false; 206 | 207 | # If all we want is the path to the Log file that will be generated, return it. 208 | if ($GetLogPath) 209 | { 210 | return $buildLogFilePath 211 | } 212 | 213 | # Try and build the solution. 214 | try 215 | { 216 | # Build the arguments to pass to MsBuild. 217 | $buildArguments = """$Path"" $MsBuildParameters /fileLoggerParameters:LogFile=""$buildLogFilePath""" 218 | 219 | # If a VS Command Prompt was found, call MSBuild from that since it sets environmental variables that may be needed to build some projects. 220 | if ($vsCommandPrompt -ne $null) 221 | { 222 | $cmdArgumentsToRunMsBuild = "/k "" ""$vsCommandPrompt"" & msbuild " 223 | } 224 | # Else the VS Command Prompt was not found, so just build using MSBuild directly. 225 | else 226 | { 227 | # Get the path to the MsBuild executable. 228 | $msBuildPath = Get-MsBuildPath 229 | $cmdArgumentsToRunMsBuild = "/k "" ""$msBuildPath"" " 230 | } 231 | 232 | # Append the MSBuild arguments to pass into cmd.exe in order to do the build. 233 | $pauseForInput = if ($ShowBuildWindowAndPromptForInputBeforeClosing) { "Pause & " } else { "" } 234 | $cmdArgumentsToRunMsBuild += "$buildArguments & $pauseForInput Exit"" " 235 | 236 | Write-Debug "Starting new cmd.exe process with arguments ""$cmdArgumentsToRunMsBuild""." 237 | 238 | # Perform the build. 239 | if ($PassThru) 240 | { 241 | return Start-Process cmd.exe -ArgumentList $cmdArgumentsToRunMsBuild -WindowStyle $windowStyle -PassThru 242 | } 243 | else 244 | { 245 | $process = Start-Process cmd.exe -ArgumentList $cmdArgumentsToRunMsBuild -WindowStyle $windowStyle -Wait -PassThru 246 | $processExitCode = $process.ExitCode 247 | } 248 | } 249 | catch 250 | { 251 | $buildCrashed = $true; 252 | $errorMessage = $_ 253 | Write-Error ("Unexpect error occured while building ""$Path"": $errorMessage" ); 254 | } 255 | 256 | # If the build crashed, return that the build didn't succeed. 257 | if ($buildCrashed) 258 | { 259 | return $false 260 | } 261 | 262 | # If we can't find the build's log file in order to inspect it, write a warning and return null. 263 | if (!(Test-Path -Path $buildLogFilePath)) 264 | { 265 | Write-Warning "Cannot find the build log file at '$buildLogFilePath', so unable to determine if build succeeded or not." 266 | return $null 267 | } 268 | 269 | # Get if the build failed or not by looking at the log file. 270 | $buildSucceeded = (((Select-String -Path $buildLogFilePath -Pattern "Build FAILED." -SimpleMatch) -eq $null) -and $processExitCode -eq 0) 271 | 272 | # If the build succeeded. 273 | if ($buildSucceeded) 274 | { 275 | # If we shouldn't keep the log around, delete it. 276 | if (!$KeepBuildLogOnSuccessfulBuilds) 277 | { 278 | Remove-Item -Path $buildLogFilePath -Force 279 | } 280 | } 281 | # Else at least one of the projects failed to build. 282 | else 283 | { 284 | # Write the error message as a warning. 285 | Write-Warning "FAILED to build ""$Path"". Please check the build log ""$buildLogFilePath"" for details." 286 | 287 | # If we should show the build log automatically, open it with the default viewer. 288 | if($AutoLaunchBuildLogOnFailure) 289 | { 290 | Start-Process -verb "Open" $buildLogFilePath; 291 | } 292 | } 293 | 294 | # Return if the Build Succeeded or Failed. 295 | return $buildSucceeded 296 | } 297 | } 298 | 299 | function Get-VisualStudioCommandPromptPath 300 | { 301 | <# 302 | .SYNOPSIS 303 | Gets the file path to the latest Visual Studio Command Prompt. Returns $null if a path is not found. 304 | 305 | .DESCRIPTION 306 | Gets the file path to the latest Visual Studio Command Prompt. Returns $null if a path is not found. 307 | #> 308 | 309 | # Get some environmental paths. 310 | $vs2010CommandPrompt = $env:VS100COMNTOOLS + "vcvarsall.bat" 311 | $vs2012CommandPrompt = $env:VS110COMNTOOLS + "VsDevCmd.bat" 312 | $vs2013CommandPrompt = $env:VS120COMNTOOLS + "VsDevCmd.bat" 313 | 314 | # Store the VS Command Prompt to do the build in, if one exists. 315 | $vsCommandPrompt = $null 316 | if (Test-Path $vs2013CommandPrompt) { $vsCommandPrompt = $vs2013CommandPrompt } 317 | elseif (Test-Path $vs2012CommandPrompt) { $vsCommandPrompt = $vs2012CommandPrompt } 318 | elseif (Test-Path $vs2010CommandPrompt) { $vsCommandPrompt = $vs2010CommandPrompt } 319 | 320 | # Return the path to the VS Command Prompt if it was found. 321 | return $vsCommandPrompt 322 | } 323 | 324 | function Get-MsBuildPath 325 | { 326 | <# 327 | .SYNOPSIS 328 | Gets the path to the latest version of MsBuild.exe. Returns $null if a path is not found. 329 | 330 | .DESCRIPTION 331 | Gets the path to the latest version of MsBuild.exe. Returns $null if a path is not found. 332 | #> 333 | 334 | # Array of valid MsBuild versions 335 | $versions = @("12.0", "4.0", "3.5", "2.0") 336 | 337 | # Loop through each version from largest to smallest. 338 | foreach ($version in $versions) 339 | { 340 | # Try to find an instance of that particular version in the registry 341 | $regKey = "HKLM:\SOFTWARE\Microsoft\MSBuild\ToolsVersions\${Version}" 342 | $itemProperty = Get-ItemProperty $RegKey -ErrorAction SilentlyContinue 343 | 344 | # If registry entry exsists, then get the msbuild path and retrun 345 | if ($itemProperty -ne $null -and $itemProperty.MSBuildToolsPath -ne $null) 346 | { 347 | # Get the path from the registry entry, and return it if it exists. 348 | $msBuildPath = Join-Path $itemProperty.MSBuildToolsPath -ChildPath "MsBuild.exe" 349 | if (Test-Path $msBuildPath) 350 | { 351 | return $msBuildPath 352 | } 353 | } 354 | } 355 | 356 | # Return that we were not able to find MsBuild.exe. 357 | return $null 358 | } 359 | Export-ModuleMember -Function Invoke-MsBuild -------------------------------------------------------------------------------- /build_stuff/cpplint/GetLatestCPPLint.sh: -------------------------------------------------------------------------------- 1 | curl -O https://raw.githubusercontent.com/cpplint/cpplint/master/cpplint.py 2 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | #Define variables 2 | CXX := g++ 3 | CXXFLAGS := -c -std=c++11 4 | 5 | OBJECTFOLDER := objects 6 | #SOURCEFOLDER := source 7 | 8 | #OBJECTS := main.cpp.o HttpClient.cpp.o HttpResponse.cpp.o StringBufferHelper.cpp.o URL.cpp.o TCPClient.cpp.o 9 | NEWSOURCE := main.cpp HttpClient.cpp HttpResponse.cpp StringBufferHelper.cpp URL.cpp TCPClient.cpp 10 | OBJECTS := $(NEWSOURCE:.cpp=.o) 11 | OBJECTSWITHPATH := $(addprefix objects/, $(OBJECTS)) 12 | 13 | #OBJBUILDPATH = $(OBJECT: path/, ) 14 | 15 | all: client 16 | 17 | #client: $(OBJECTS) 18 | # $(CXX) objects/$(OBJECTS) -o client 19 | 20 | #VPATH = src:objects 21 | 22 | client: $(OBJECTS) 23 | $(CXX) $(OBJECTSWITHPATH) -o bin/client 24 | 25 | #client: %.o 26 | # $(CXX) $< -o client 27 | 28 | %.o: source/%.cpp 29 | $(CXX) $(CXXFLAGS) $< -o objects/$@ 30 | 31 | #main.cpp.o: main.cpp 32 | # $(CXX) -c main.cpp 33 | 34 | #HttpClient.o: HttpClient.cpp HttpClient.h 35 | # $(CXX) -c HttpClient.cpp HttpClient.h 36 | 37 | #HttpResponse.o: HttpResponse.cpp HttpResponse.h 38 | # $(CXX) -c HttpResponse.cpp HttpResponse.h 39 | 40 | #StringBufferHelper.o: StringBufferHelper.cpp StringBufferHelper.h 41 | # $(CXX) -c StringBufferHelper.cpp StringBufferHelper.h 42 | 43 | #TCPClient.o: TCPClient.cpp TCPClient.h 44 | # $(CXX) -c $< 45 | 46 | 47 | 48 | #hello.o: hello.cpp 49 | # g++ -c hello.cpp 50 | 51 | clean: 52 | rm -rf objects/*.o 53 | rm -rf bin/client 54 | -------------------------------------------------------------------------------- /source/HttpClient.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2014 EmilW 2 | 3 | #include "source/HttpClient.h" 4 | #include "source/URL.h" 5 | #include "source/TCPClient.h" 6 | 7 | using std::string; 8 | 9 | HttpClient::HttpClient() { 10 | } 11 | 12 | HttpClient::HttpClient(Log log) { 13 | _log = log; 14 | } 15 | 16 | // This needs to be refactored to go away from command line style 17 | HttpResponse HttpClient::RunRequest(string url, string type) { 18 | URL* urlObject = new URL(url); 19 | TCPClient client; 20 | string message, result; 21 | message = type + " " + urlObject->GetRelativePath() + " HTTP/1.1\r\n" \ 22 | + "Host: " + urlObject->GetHostName() + "\r\n" \ 23 | + "\r\n"; 24 | 25 | _log.Add("Making call with hostname: " + urlObject->GetHostName()); 26 | _log.Add("Port number: " + urlObject->GetPortNumber()); 27 | _log.Add("Message: \n" + message); 28 | 29 | if (urlObject->IsSSL()) { 30 | _log.Add("Use https for the call"); 31 | result = client.SendOverSSL(urlObject->GetHostName(), 32 | urlObject->GetPortNumber(), message); 33 | } else { 34 | _log.Add("Use http for the call"); 35 | result = client.Send(urlObject->GetHostName(), 36 | urlObject->GetPortNumber(), message); 37 | } 38 | _log.Add("Request was made, parsing result"); 39 | HttpResponse response(result, urlObject, _log); 40 | _log.Add("Response was parsed sucessfully"); 41 | return response; 42 | } 43 | 44 | Log HttpClient::GetFullLog() { 45 | return _log; 46 | } 47 | -------------------------------------------------------------------------------- /source/HttpClient.h: -------------------------------------------------------------------------------- 1 | // Copyright 2014 EmilW 2 | 3 | #ifndef SOURCE_HTTPCLIENT_H_ 4 | #define SOURCE_HTTPCLIENT_H_ 5 | 6 | #include 7 | #include "HttpResponse.h" 8 | #include "Log.h" 9 | 10 | class HttpClient { 11 | public: 12 | HttpClient(); 13 | explicit HttpClient(Log log); 14 | HttpResponse RunRequest(std::string url, std::string type); 15 | Log GetFullLog(); 16 | private: 17 | Log _log; 18 | }; 19 | 20 | #endif // SOURCE_HTTPCLIENT_H_ 21 | -------------------------------------------------------------------------------- /source/HttpResponse.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2014 EmilW 2 | #include "source/HttpResponse.h" 3 | #include 4 | #include 5 | #include 6 | 7 | using std::string; 8 | 9 | HttpResponse::HttpResponse(string responseData, URL* originalURL, 10 | Log log) { 11 | _log = log; 12 | _requestURL = originalURL; 13 | _log.Add("HttpResponse", "Starting parsing"); 14 | 15 | if (responseData.substr(0, 5) == "ERROR") { 16 | _httpStatusCode = "999"; 17 | _httpStatusText = responseData.substr(5, responseData.size()-5); 18 | _log.Add("Client handled error occured"); 19 | } else { 20 | _pRawBuffer = new StringBufferHelper(responseData); 21 | parseHttpResponseData(); 22 | _log.Add("HttpResponse", "Parsing of response went ok"); 23 | } 24 | } 25 | 26 | URL* HttpResponse::GetRequestURL() { 27 | return _requestURL; 28 | } 29 | 30 | string HttpResponse::moveBufferForward(string buffer, int newPosition) { 31 | return buffer.substr(newPosition+1, buffer.size()); 32 | } 33 | 34 | void HttpResponse::parseHttpResponseData() { 35 | parseHttpEnvelope(); 36 | parseHttpHeaders(); 37 | } 38 | 39 | void HttpResponse::parseHttpEnvelope() { 40 | _httpVersion = _pRawBuffer->GetNextSegmentBySeparator(" "); 41 | _httpStatusCode = _pRawBuffer->GetNextSegmentBySeparator(" "); 42 | _httpStatusText = _pRawBuffer->GetNextSegmentBySeparator("\n"); 43 | } 44 | 45 | void HttpResponse::parseHttpHeaders() { 46 | string key, value; 47 | 48 | while (true) { 49 | key = _pRawBuffer->GetNextSegmentBySeparator(": "); 50 | if (key == "NA") 51 | break; 52 | value = _pRawBuffer->GetNextSegmentBySeparator("\n"); 53 | _headerMap.insert(std::pair(key, value)); 54 | } 55 | } 56 | 57 | string HttpResponse::GetHttpVersion() { 58 | return _httpVersion; 59 | } 60 | 61 | string HttpResponse::GetHttpStatusCode() { 62 | return _httpStatusCode; 63 | } 64 | 65 | string HttpResponse::GetHttpStatusText() { 66 | return _httpStatusText; 67 | } 68 | 69 | std::map HttpResponse::GetHttpHeaders() { 70 | return _headerMap; 71 | } 72 | 73 | string HttpResponse::GetRawResponse() { 74 | if (_pRawBuffer != nullptr) 75 | return _pRawBuffer->GetRawData(); 76 | return ""; 77 | } 78 | -------------------------------------------------------------------------------- /source/HttpResponse.h: -------------------------------------------------------------------------------- 1 | // Copyright 2014 EmilW 2 | 3 | #ifndef SOURCE_HTTPRESPONSE_H_ 4 | #define SOURCE_HTTPRESPONSE_H_ 5 | 6 | #include 7 | #include 8 | #include "StringBufferHelper.h" 9 | #include "URL.h" 10 | #include "Log.h" 11 | 12 | class HttpResponse { 13 | public: 14 | HttpResponse(std::string responseData, URL* originalURL, Log log); 15 | std::string GetHttpStatusCode(); 16 | std::string GetHttpStatusText(); 17 | std::string GetRawResponse(); 18 | std::string GetHttpVersion(); 19 | std::map GetHttpHeaders(); 20 | URL* GetRequestURL(); 21 | private: 22 | std::string moveBufferForward(std::string buffer, int newPosition); 23 | void parseHttpResponseData(); 24 | void parseHttpEnvelope(); 25 | void parseHttpHeaders(); 26 | StringBufferHelper* _pRawBuffer; 27 | std::string _httpStatusCode; 28 | std::string _httpStatusText; 29 | std::string _httpVersion; 30 | std::map _headerMap; 31 | URL* _requestURL; 32 | Log _log; 33 | }; 34 | 35 | #endif // SOURCE_HTTPRESPONSE_H_ 36 | -------------------------------------------------------------------------------- /source/Log.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2014 EmilW 2 | 3 | #include "source/Log.h" 4 | #include 5 | #include 6 | 7 | using std::string; 8 | 9 | Log::Log() { 10 | _printFunction = nullptr; 11 | } 12 | 13 | Log::Log(void (*printFunction)(string textToPrint)) { 14 | _printFunction = printFunction; 15 | } 16 | 17 | string Log::GetFullLogAsText() { 18 | return _logText; 19 | } 20 | 21 | void Log::Add(string message) { 22 | _logText + "\n" + message; 23 | if (_printFunction != nullptr) { 24 | _printFunction(message); 25 | } 26 | } 27 | 28 | void Log::Add(string prefix, string message) { 29 | Add("[" + prefix + "] " + message); 30 | } 31 | -------------------------------------------------------------------------------- /source/Log.h: -------------------------------------------------------------------------------- 1 | // Copyright 2014 EmilW 2 | 3 | #ifndef SOURCE_LOG_H_ 4 | #define SOURCE_LOG_H_ 5 | #include 6 | 7 | using std::string; 8 | 9 | class Log { 10 | public: 11 | Log(); 12 | explicit Log(void (*printFunction)(string textToPrint)); 13 | void Add(string message); 14 | void Add(string prefix, string message); 15 | string GetFullLogAsText(); 16 | private: 17 | string _logText; 18 | void (*_printFunction)(string textToPrint); 19 | }; 20 | 21 | 22 | #endif // SOURCE_LOG_H_ 23 | -------------------------------------------------------------------------------- /source/StringBufferHelper.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2014 EmilW 2 | #include "source/StringBufferHelper.h" 3 | // #include 4 | using std::string; 5 | 6 | StringBufferHelper::StringBufferHelper(std::string buffer) { 7 | _buffer = buffer; 8 | _currentPosition = 0; 9 | } 10 | 11 | string StringBufferHelper::MoveBufferForward(int newPosition) { 12 | _currentPosition = newPosition; 13 | return _buffer.substr(_currentPosition, _buffer.size()); 14 | } 15 | 16 | string StringBufferHelper::GetRawData() { 17 | return _buffer; 18 | } 19 | 20 | string StringBufferHelper::GetNextSegmentBySeparator(std::string separator) { 21 | string currentBuffer = _buffer.substr(_currentPosition, _buffer.size()); 22 | int position = currentBuffer.find(separator); 23 | 24 | if (position == string::npos) { 25 | return "NA"; 26 | } 27 | 28 | string segment = currentBuffer.substr(0, position); 29 | _currentPosition = _currentPosition + (position + 1); 30 | 31 | return segment; 32 | } 33 | -------------------------------------------------------------------------------- /source/StringBufferHelper.h: -------------------------------------------------------------------------------- 1 | // Copyright 2014 EmilW 2 | 3 | #ifndef SOURCE_STRINGBUFFERHELPER_H_ 4 | #define SOURCE_STRINGBUFFERHELPER_H_ 5 | 6 | #include 7 | using std::string; 8 | 9 | class StringBufferHelper { 10 | public: 11 | explicit StringBufferHelper(string buffer); 12 | string MoveBufferForward(int newPosition); 13 | string GetRawData(); 14 | string GetNextSegmentBySeparator(string separator); 15 | private: 16 | string _buffer; 17 | int _currentPosition; 18 | }; 19 | 20 | 21 | #endif // SOURCE_STRINGBUFFERHELPER_H_ 22 | -------------------------------------------------------------------------------- /source/TCPClient.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2014 EmilW 2 | 3 | #include "source/TCPClient.h" 4 | #include 5 | #include // Needed for memset 6 | #ifdef _WIN32 7 | #include 8 | #include 9 | #else 10 | #include // Needed for the socket functions 11 | #include // Needed for the socket functions 12 | #include 13 | #endif 14 | 15 | const int BUFFERSIZE = 1000; 16 | 17 | #ifdef _WIN32 18 | string TCPClient::SendWin(string hostname, string portNumber, string message) { 19 | struct addrinfo host_info; 20 | struct addrinfo *host_info_list = nullptr; 21 | struct addrinfo *host_info_first = nullptr; 22 | int status = 0; 23 | WSADATA wsaData; 24 | 25 | // Windows specific 26 | WSAStartup(MAKEWORD(2, 2), &wsaData); 27 | if (status != 0) { 28 | printf("WSAStartup failed: %d\n", status); 29 | return std::string("ERROR: Could not initialize winsock"); 30 | } 31 | 32 | // Init address structure 33 | ZeroMemory(&host_info, sizeof(host_info)); 34 | host_info.ai_family = AF_UNSPEC; 35 | host_info.ai_socktype = SOCK_STREAM; 36 | host_info.ai_protocol = IPPROTO_TCP; 37 | status = getaddrinfo(hostname.c_str(), portNumber.c_str(), 38 | &host_info, &host_info_list); 39 | 40 | if (status != 0) { 41 | WSACleanup(); 42 | return std::string("ERROR: Hostname could not be resolved"); 43 | } 44 | 45 | SOCKET socketfd = INVALID_SOCKET; 46 | host_info_first = host_info_list; 47 | 48 | socketfd = socket(host_info_first->ai_family, host_info_first->ai_socktype, 49 | host_info_first->ai_protocol); 50 | if (socketfd == INVALID_SOCKET) { 51 | printf("Error at socket(): %ld\n", WSAGetLastError()); 52 | freeaddrinfo(host_info_list); 53 | WSACleanup(); 54 | return std::string("ERROR: Could not open socket"); 55 | } 56 | 57 | status = connect(socketfd, host_info_first->ai_addr, 58 | static_cast(host_info_first->ai_addrlen)); 59 | if (status == SOCKET_ERROR) { 60 | closesocket(socketfd); 61 | socketfd = INVALID_SOCKET; 62 | freeaddrinfo(host_info_list); 63 | WSACleanup(); 64 | return std::string("ERROR: Could not connect"); 65 | } 66 | 67 | std::string msg = message; 68 | int len; 69 | int bytes_sent; 70 | len = strlen(msg.c_str()); 71 | bytes_sent = send(socketfd, msg.c_str(), len, 0); 72 | 73 | if (bytes_sent == SOCKET_ERROR) { 74 | closesocket(socketfd); 75 | WSACleanup(); 76 | return std::string("Failed to send message on socket"); 77 | } 78 | 79 | // Close send socket 80 | status = shutdown(socketfd, SD_SEND); 81 | if (status == SOCKET_ERROR) { 82 | printf("shutdown failed: %d\n", WSAGetLastError()); 83 | closesocket(socketfd); 84 | WSACleanup(); 85 | return std::string("Failed to close sending socket"); 86 | } 87 | 88 | int bytes_recieved; 89 | char incomming_data_buffer[BUFFERSIZE]; 90 | 91 | do { 92 | status = recv(socketfd, incomming_data_buffer, BUFFERSIZE, 0); 93 | if (status > 0) 94 | printf("Bytes received: %d\n", status); 95 | else if (status == 0) 96 | printf("Connection closed\n"); 97 | else 98 | printf("recv failed: %d\n", WSAGetLastError()); 99 | } while (status > 0); 100 | 101 | return std::string(incomming_data_buffer); 102 | } 103 | #else 104 | string TCPClient::Sendnix(string hostname, string portNumber, string message) { 105 | // TCP client 106 | int status; 107 | // The struct that getaddrinfo() fills up with data. 108 | struct addrinfo host_info; 109 | // Pointer to the to the linked list of host_info's. 110 | struct addrinfo *host_info_list; 111 | 112 | /* The MAN page of getaddrinfo() states "All the other fields in the structure pointed 113 | to by hints must contain either 0 or a null pointer, as appropriate." When a struct 114 | is created in c++, it will be given a block of memory. This memory is not nessesary 115 | empty. Therefor we use the memset function to make sure all fields are NULL. 116 | */ 117 | memset(&host_info, 0, sizeof host_info); 118 | 119 | host_info.ai_family = AF_UNSPEC; // IP version not specified. Can be both. 120 | // Use SOCK_STREAM for TCP or SOCK_DGRAM for UDP. 121 | host_info.ai_socktype = SOCK_STREAM; 122 | 123 | /* Now fill up the linked list of host_info structs with google's address information. 124 | status = getaddrinfo("www.google.com", "80", &host_info, &host_info_list);*/ 125 | status = getaddrinfo(hostname.c_str(), portNumber.c_str(), &host_info, 126 | &host_info_list); 127 | // getaddrinfo returns 0 on succes, or some other value when an error occured. 128 | // (translated into human readable text by the gai_gai_strerror function). 129 | if (status != 0) { 130 | return std::string("ERROR: Hostname could not be resolved"); 131 | } 132 | 133 | int socketfd; // The socket descripter 134 | socketfd = socket(host_info_list->ai_family, host_info_list->ai_socktype, 135 | host_info_list->ai_protocol); 136 | if (socketfd == -1) { 137 | return std::string("ERROR: Could not open socket"); 138 | } 139 | 140 | status = connect(socketfd, host_info_list->ai_addr, 141 | host_info_list->ai_addrlen); 142 | if (status == -1) { 143 | return std::string("ERROR: Could not connect"); 144 | } 145 | 146 | std::string msg = message; 147 | int len; 148 | ssize_t bytes_sent; 149 | len = strlen(msg.c_str()); 150 | bytes_sent = send(socketfd, msg.c_str(), len, 0); 151 | 152 | ssize_t bytes_recieved; 153 | char incomming_data_buffer[1000]; 154 | bytes_recieved = recv(socketfd, incomming_data_buffer, 1000, 0); 155 | /*If no data arrives, the program will just wait here until 156 | some data arrives.*/ 157 | if (bytes_recieved == 0) { 158 | return std::string("ERROR: Host shut down"); 159 | } 160 | if (bytes_recieved == -1) { 161 | return std::string("ERROR: Error when recieving"); 162 | } 163 | incomming_data_buffer[bytes_recieved] = '\0'; 164 | 165 | freeaddrinfo(host_info_list); 166 | 167 | close(socketfd); 168 | 169 | return std::string(incomming_data_buffer); 170 | } 171 | #endif 172 | 173 | string TCPClient::Send(string hostname, string portNumber, string message) { 174 | // To be used to make it platform independent 175 | #ifdef __linux__ 176 | std::cout << "In Linux\n"; 177 | #elif _WIN32 178 | std::cout << "In Windows\n"; 179 | #elif __APPLE__ 180 | std::cout << "Mac Os X\n"; 181 | #else 182 | std::cout << "Unknown system \n"; 183 | #endif 184 | 185 | // Select the correct platform 186 | #ifdef __linux__ 187 | return this->Sendnix(hostname, portNumber, message); 188 | #elif __APPLE__ 189 | return this->Sendnix(hostname, portNumber, message); 190 | #elif _WIN32 191 | return this->SendWin(hostname, portNumber, message); 192 | #endif 193 | } 194 | 195 | string TCPClient::SendOverSSL(string hostname, string portNumber, 196 | string message) { 197 | return std::string("ERROR: HTTPS is not supported yet!"); 198 | } 199 | -------------------------------------------------------------------------------- /source/TCPClient.h: -------------------------------------------------------------------------------- 1 | // Copyright 2014 EmilW 2 | 3 | #ifndef SOURCE_TCPCLIENT_H_ 4 | #define SOURCE_TCPCLIENT_H_ 5 | 6 | #include 7 | 8 | using std::string; 9 | 10 | class TCPClient { 11 | public: 12 | string Send(string hostname, string portNumber, string message); 13 | string SendWin(string hostname, string portNumber, string message); 14 | string Sendnix(string hostname, string portNumber, string message); 15 | string SendOverSSL(string hostname, string portNumber, string message); 16 | }; 17 | 18 | #endif // SOURCE_TCPCLIENT_H_ 19 | -------------------------------------------------------------------------------- /source/URL.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2014 EmilW 2 | 3 | #include "source/URL.h" 4 | // #include 5 | 6 | using std::string; 7 | 8 | URL::URL(std::string url) { 9 | _url = url; 10 | // Get the protocoll end pos 11 | int protocollPos = url.find("://"); 12 | 13 | if (protocollPos == std::string::npos) { 14 | _protocoll = REGULARPROTOCOL; 15 | protocollPos = 0; 16 | } else { 17 | _protocoll = url.substr(0, protocollPos); 18 | // Remove the protocoll part from the url 19 | url = url.substr(protocollPos+3, url.size()); 20 | } 21 | 22 | /* Find the hostname ended by / or by : depending on if 23 | port is specified or not */ 24 | 25 | int hostNameEndPos = url.find("/"); 26 | int portEndPos = url.find(":"); 27 | 28 | int queryStringStartPos = url.find("?"); 29 | 30 | // If the port position do not exists, set default to 80 31 | if (portEndPos == std::string::npos) { 32 | if (this->GetProtocoll() == SECUREPROTOCOL) { 33 | _portNumber = SECUREPROTOCOLPORT; 34 | } else { 35 | _portNumber = REGULAREPROTOCOLPORT; 36 | } 37 | } else { 38 | /* If there is nothing more than the hostname e.g. www.google.com, 39 | get the last position 40 | */ 41 | if (hostNameEndPos == string::npos) { 42 | hostNameEndPos = url.size(); 43 | } 44 | // If there is a port specified, e.g. www.google.com:80/subfolder 45 | _portNumber = url.substr(portEndPos+1, hostNameEndPos-(portEndPos+1)); 46 | _host = url.substr(0, portEndPos); 47 | } 48 | 49 | // If the host was not set by due to that the port was not specified 50 | if (_host == "") { 51 | if (hostNameEndPos == string::npos) { 52 | _host = url; 53 | } else { 54 | _host = url.substr(0, hostNameEndPos); 55 | } 56 | } 57 | 58 | // Set the relative part of the URL 59 | if (hostNameEndPos != string::npos) { 60 | _relativePath = url.substr(hostNameEndPos, url.size()-hostNameEndPos); 61 | } 62 | 63 | // Set the query string part of the URL 64 | if (queryStringStartPos != string::npos) { 65 | _queryString = url.substr(queryStringStartPos, 66 | url.size()-queryStringStartPos); 67 | } 68 | } 69 | 70 | std::string URL::GetHostName() { 71 | return _host; 72 | } 73 | 74 | std::string URL::GetProtocoll() { 75 | return _protocoll; 76 | } 77 | 78 | std::string URL::GetPortNumber() { 79 | return _portNumber; 80 | } 81 | 82 | std::string URL::GetFullURL() { 83 | return _url; 84 | } 85 | 86 | std::string URL::GetRelativePath() { 87 | if (_relativePath.length() == 0) 88 | return "/"; 89 | return _relativePath; 90 | } 91 | 92 | std::string URL::GetQueryString() { 93 | return _queryString; 94 | } 95 | 96 | bool URL::IsSSL() { 97 | if (this->GetProtocoll() == SECUREPROTOCOL) 98 | return true; 99 | else 100 | return false; 101 | } 102 | -------------------------------------------------------------------------------- /source/URL.h: -------------------------------------------------------------------------------- 1 | // Copyright 2014 EmilW 2 | 3 | #ifndef SOURCE_URL_H_ 4 | #define SOURCE_URL_H_ 5 | 6 | #include 7 | 8 | class URL { 9 | public: 10 | explicit URL(std::string url); 11 | std::string GetHostName(); 12 | std::string GetProtocoll(); 13 | std::string GetPortNumber(); 14 | std::string GetFullURL(); 15 | std::string GetRelativePath(); 16 | std::string GetQueryString(); 17 | bool IsSSL(); 18 | private: 19 | std::string _url; 20 | std::string _host; 21 | std::string _protocoll; 22 | std::string _portNumber; 23 | std::string _relativePath; 24 | std::string _queryString; 25 | 26 | const std::string SECUREPROTOCOLPORT = "443"; 27 | const std::string REGULAREPROTOCOLPORT = "80"; 28 | const std::string REGULARPROTOCOL = "http"; 29 | const std::string SECUREPROTOCOL = "https"; 30 | }; 31 | 32 | 33 | #endif // SOURCE_URL_H_ 34 | -------------------------------------------------------------------------------- /source/main.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2014 EmilW 2 | 3 | #include 4 | #include 5 | #include 6 | #include "HttpClient.h" 7 | 8 | void printOut(std::string message) { 9 | std::cout << "CPrint: " << message << "\n"; 10 | } 11 | 12 | int main(int argc, char **argv) { 13 | std::string adress; 14 | if (argc > 1) { 15 | adress = argv[1]; 16 | } else { 17 | std::cout << "No URL adress provided" << "\n"; 18 | return -1; 19 | } 20 | 21 | Log log(printOut); 22 | HttpClient client(log); 23 | 24 | try { 25 | HttpResponse response = client.RunRequest(adress, "GET"); 26 | printOut("Client was called, ok!"); 27 | URL* urlObject = response.GetRequestURL(); 28 | 29 | if (urlObject == nullptr) { 30 | std::cout << "The URL is dead"; 31 | } 32 | 33 | printOut("Request information-------------------"); 34 | printOut("Full URL: " + urlObject->GetFullURL()); 35 | printOut("Protocoll: " + urlObject->GetProtocoll()); 36 | printOut("Host name: " + urlObject->GetHostName()); 37 | printOut("Port number: " + urlObject->GetPortNumber()); 38 | 39 | printOut("Basic information---------------------"); 40 | printOut("Version: " + response.GetHttpVersion()); 41 | printOut("Status code: " + response.GetHttpStatusCode()); 42 | printOut("Status text: " + response.GetHttpStatusText()); 43 | 44 | printOut("Header information---------------------"); 45 | std::map headers = response.GetHttpHeaders(); 46 | std::map::iterator it; 47 | for (it=headers.begin(); it != headers.end(); ++it) { 48 | printOut(it->first + ": " + it->second); 49 | } 50 | printOut("Raw response-------------------------"); 51 | printOut(response.GetRawResponse()); 52 | } catch (int e) { 53 | printOut("An unhandled exception occured"); 54 | } 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /source/tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 2.6) 2 | project (HttpClientTests) 3 | include(ExternalProject) 4 | 5 | #ExternalProject_Get_Property(bin_dir sourceFiles) 6 | 7 | #foreach(sourceFile ${source_files}) 8 | # set(sourceFile_val ../../${sourceFile}) 9 | #endforeach(sourceFile) 10 | 11 | add_executable(HttpClientTests catch.hpp URLTests.cpp CallTests.cpp ../URL.h ../URL.cpp ../StringBufferHelper.h ../StringBufferHelper.cpp ../Log.h ../Log.cpp ../TCPClient.h ../TCPClient.cpp ../HttpResponse.h ../HttpResponse.cpp ../HttpClient.h ../HttpClient.cpp) 12 | add_test("all_tests" HttpClientTests) -------------------------------------------------------------------------------- /source/tests/CallTests.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Emil W 2 | 3 | #include "source/HttpClient.h" 4 | #include "catch.hpp" 5 | #include 6 | 7 | TEST_CASE("Cal tests", "GET") { 8 | HttpClient* httpClient; 9 | string statusCode; 10 | 11 | SECTION("GET") { 12 | SECTION(" With full URL") { 13 | httpClient = new HttpClient(); 14 | statusCode = httpClient->RunRequest("http://httpbin.org/get", "GET") 15 | .GetHttpStatusCode(); 16 | } 17 | SECTION(" with short form") { 18 | httpClient = new HttpClient(); 19 | statusCode = httpClient->RunRequest("httpbin.org/get", "GET") 20 | .GetHttpStatusCode(); 21 | } 22 | SECTION(" without trailing /") { 23 | httpClient = new HttpClient(); 24 | statusCode = httpClient->RunRequest("www.example.com", "GET") 25 | .GetHttpStatusCode(); 26 | } 27 | CHECK(statusCode == "200"); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /source/tests/GetLatestCatch.sh: -------------------------------------------------------------------------------- 1 | curl -O https://raw.githubusercontent.com/philsquared/Catch/master/single_include/catch.hpp 2 | -------------------------------------------------------------------------------- /source/tests/URLTests: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emilw/HttpClient/14c02e5d3970542c5c12bba2b075bbbd1eeaec23/source/tests/URLTests -------------------------------------------------------------------------------- /source/tests/URLTests.cpp: -------------------------------------------------------------------------------- 1 | #define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do this in one cpp file 2 | #include "catch.hpp" 3 | #include "../URL.h" 4 | 5 | TEST_CASE( "Create regular URL", "URLTests" ) { 6 | 7 | URL* urlObject; 8 | 9 | SECTION( "regulr http" ) { 10 | SECTION(" with full URL"){ 11 | urlObject = new URL("http://testing.com"); 12 | } 13 | SECTION(" with short form"){ 14 | urlObject = new URL("testing.com"); 15 | } 16 | REQUIRE_FALSE(urlObject->IsSSL()); 17 | CHECK(urlObject->GetPortNumber() == "80"); 18 | CHECK(urlObject->GetProtocoll() == "http"); 19 | } 20 | SECTION( "with https" ) { 21 | SECTION(" with full URL"){ 22 | urlObject = new URL("https://testing.com"); 23 | } 24 | REQUIRE(urlObject->IsSSL()); 25 | CHECK(urlObject->GetPortNumber() == "443"); 26 | CHECK(urlObject->GetProtocoll() == "https"); 27 | } 28 | 29 | SECTION( "with specified port" ) { 30 | 31 | urlObject = new URL("https://testing.com:8080"); 32 | REQUIRE(urlObject->IsSSL()); 33 | CHECK(urlObject->GetPortNumber() == "8080"); 34 | } 35 | 36 | SECTION( "with sub folders(long port) " ) { 37 | 38 | urlObject = new URL("https://testing.com:8080/testfolder"); 39 | REQUIRE(urlObject->IsSSL()); 40 | CHECK(urlObject->GetPortNumber() == "8080"); 41 | CHECK(urlObject->GetRelativePath() == "/testfolder"); 42 | } 43 | 44 | SECTION( "with sub folders(short port) " ) { 45 | 46 | urlObject = new URL("https://testing.com:88/testfolder"); 47 | REQUIRE(urlObject->IsSSL()); 48 | CHECK(urlObject->GetPortNumber() == "88"); 49 | } 50 | 51 | SECTION( "with query string parameters " ) { 52 | 53 | urlObject = new URL("https://testing.com:88/testfolder?testPar1=2344&testPar3=3345"); 54 | REQUIRE(urlObject->IsSSL()); 55 | CHECK(urlObject->GetPortNumber() == "88"); 56 | CHECK(urlObject->GetQueryString() == "?testPar1=2344&testPar3=3345"); 57 | } 58 | 59 | CHECK(urlObject->GetHostName() == "testing.com"); 60 | } --------------------------------------------------------------------------------