bool HttpReqImpl::enumHeader(Message<bool, HeaderFieldPair> caller) const {
	for (HeaderMap::Iterator iter = requestHdrs.getFwIter(); iter.hasItems();) {
		const HeaderMap::Entity& e = iter.getNext();
		if (caller(HeaderFieldPair(e.key, e.value)))
			return true;
	}
	return false;
}
void HttpReqImpl::sendHeaders() {
	if (bHeaderSent)
		return;

	if (bNeedContinue) {
		remainPostData = 0;
		chunkedPost = false;
	}
	bNeedContinue = false;

	bool hasServer = false;
	bool hasContentType = false;
	bool hasTransfEnc = false;
	bool hasConnection = false;
	bool hasLength = false;
	bool hasDate = false;
	static ConstStrA contentTypeKey = getHeaderFieldName(fldContentType);
	static ConstStrA serverKey = getHeaderFieldName(fldServer);
	static ConstStrA transfEnc = getHeaderFieldName(fldTransferEncoding);
	static ConstStrA connectionStr = getHeaderFieldName(fldConnection);
	static ConstStrA contenLenStr = getHeaderFieldName(fldContentLength);
	static ConstStrA dateStr = getHeaderFieldName(fldDate);
	ConstStrA statusMsgStr = this->statusMsg;
	if (statusMsgStr.empty())
		statusMsgStr = getStatusMessage(statusCode);


	PrintTextA print(*inout);
	print.setNL("\r\n");
	print("HTTP/%1.%2 %3 %4\n") << httpMajVer << httpMinVer << statusCode
			<< statusMsgStr;

	if (statusCode == 101) {
		hasTransfEnc = hasConnection = hasContentType = true;
		useChunked = false;
		remainPostData = naturalNull;
		switchedProtocol = true;
		TimeStamp reqEndTime = TimeStamp::now();
		natural reqTime = (reqEndTime - reqBeginTime).getMilis();
		logRequest(reqTime);
	}

	for (HeaderMap::Iterator iter = responseHdrs.getFwIter(); iter.hasItems();) {
		const HeaderMap::Entity hdrPair = iter.getNext();
		if (!hasContentType && hdrPair.key == contentTypeKey)
			hasContentType = true;

		if (!hasServer && hdrPair.key == serverKey)
			hasServer = true;

		if (!hasTransfEnc && hdrPair.key == transfEnc)
			hasTransfEnc = !(useChunked && hdrPair.value == ConstStrA("chunked"));

		if (!hasConnection && hdrPair.key == connectionStr)
			hasConnection = true;

		if (!hasDate && hdrPair.key == dateStr)
			hasDate = true;

		if (!hasLength && hdrPair.key == contenLenStr) {
			hasLength = true;
		}

		print("%1: %2\n") << ConstStrA(hdrPair.key) << ConstStrA(hdrPair.value);
	}
	if (!hasContentType)
		print("%1: %2\n") << contentTypeKey << "text/html;charset=UTF-8";

	if (!hasServer)
		print("%1: %2\n") << serverKey << serverIdent;

	if (hasLength) {
		useChunked = false;
	}

	if (!hasDate) {
		TimeStamp::RFC1123Time datenow = TimeStamp::now().asRFC1123Time();
		print("%1: %2\n") << dateStr << ConstStrA(datenow);
	}

	if (!hasTransfEnc && useChunked && !closeConn)
		print("%1: %2\n") << transfEnc << "chunked";
	else
		useChunked = false;

	if (!hasConnection && closeConn)
		print("%1: %2\n") << connectionStr << "close";

	print("\n");

/*	LogObject(THISLOCATION).progress("%7 - %3 %4 HTTP/%1.%2 %5 %6")
		<< httpMajVer << httpMajVer << ConstStrA(method)
		<< ConstStrA(path) << statusCode << statusMsgStr
		<< getIfc<IHttpPeerInfo>().getPeerRealAddr();*/

	responseHdrs.clear();
	//for code 100 or 101, additional header will be next
	if (statusCode == 100) {
		//set status code 200 to simply processing reply (handler don't need to reset 100 status
		statusCode = 200;
		//unset message
		this->statusMsg = HdrStr();
		//now, handler can exit function with status 100 - when data arrives, onData will be called
	} else {
		//header sent, prevent sending new headers
		bHeaderSent = true;
	}
}
Beispiel #3
0
void WinHttpStream::initRequest()
{
	TextParser<wchar_t> parser;
	if (!parser(L"%1://%[*-_.a-zA-Z0-9:@]2%%[/](*)*3",url))
		throw FileOpenError(THISLOCATION,ERROR_FILE_NOT_FOUND,url);

	String protocol = parser[1].str();
	String hostident = parser[2].str();
	String::SplitIterator hostidentsplit = hostident.split('@');
	String ident;
	String domain;
	domain = hostidentsplit.getNext();
	while (hostidentsplit.hasItems()) {
		ident = ident + domain + ConstStrW('@');
		domain = hostidentsplit.getNext();
	}
	String path = parser[3].str();
	natural port;
	String username;
	String password;
	bool secure;

	if (parser( L"%1:%u2",domain)) {
		domain = parser[1].str();
		port = parser[2];
		secure = false;
	} else if (protocol == ConstStrW(L"http")) {
		port = INTERNET_DEFAULT_HTTP_PORT;
		secure = false;
	} else if (protocol == ConstStrW(L"https")) {
		port = INTERNET_DEFAULT_HTTPS_PORT;
		secure = true;
	} else
		throw FileOpenError(THISLOCATION,ERROR_NOT_FOUND,url);

	if (!ident.empty()) {
		if (parser(L"%1:%2@",ident))  {
			username = parser[1].str();
			password = parser[2].str();
		} else {
			throw FileMsgException(THISLOCATION,0,url,"Invalid identification field in the url");
		}
	}
	DWORD accessType;
	switch (settings.proxyMode) {
	case pmManual:  accessType = INTERNET_OPEN_TYPE_PROXY;
	case pmDirect:  accessType = INTERNET_OPEN_TYPE_DIRECT;
	case pmAuto:  accessType = INTERNET_OPEN_TYPE_PRECONFIG;
	}

	TextFormatBuff<wchar_t> fmt;

	String proxyName;
	if (accessType == INTERNET_OPEN_TYPE_PROXY) {
		fmt(L"%1:%2") << settings.proxyAddr << settings.proxyPort;
		proxyName = fmt.write();
	}

	if (hInternet) InternetCloseHandle(hInternet);
	hInternet = InternetOpenW(settings.userAgent.cStr(),accessType,proxyName.cStr(),0,0);
	if (hInternet == 0) 
		throw FileMsgException(THISLOCATION,GetLastError(),url,"Cannot initialize WinInet");

	if (hConnect) InternetCloseHandle(hConnect);
	hConnect = InternetConnectW(hInternet,domain.cStr(),(INTERNET_PORT)port,
		username.empty()?0:username.cStr(),
		password.empty()?0:password.cStr(),
		INTERNET_SERVICE_HTTP ,0,0);
	if (hConnect == 0) 
		throw FileMsgException(THISLOCATION,GetLastError(),url,"Cannot connect remote site");
	
	DWORD reqFlags = INTERNET_FLAG_NO_UI |INTERNET_FLAG_HYPERLINK ;
	if (redirDisabled) reqFlags|=INTERNET_FLAG_NO_AUTO_REDIRECT ;
	if (!settings.cookiesEnabled) reqFlags|=INTERNET_FLAG_NO_COOKIES;
	if (secure) reqFlags|=INTERNET_FLAG_SECURE;
	

	hHTTPConn = HttpOpenRequestW(hConnect,String(method).cStr(),path.cStr(),
					0,0,0,reqFlags,0);
	if (hHTTPConn == 0) 
		throw FileMsgException(THISLOCATION,GetLastError(),url,"Cannot connect remote site");
	AutoArray<wchar_t> hdrall;
	for (HeaderMap::Iterator iter = hdrmap.getFwIter(); iter.hasItems();) {

		const HeaderMap::Entity &e = iter.getNext();
		fmt(L"%1: %2\n") << e.key << e.value;
		hdrall.append(fmt.write());
	}	
	if (!hdrall.empty() &&
		!HttpAddRequestHeadersW(hHTTPConn,hdrall.data(),(DWORD)hdrall.length(),HTTP_ADDREQ_FLAG_REPLACE|HTTP_ADDREQ_FLAG_ADD))
		throw FileMsgException(THISLOCATION,GetLastError(),url,"AddRequest failed");
	
	if (!HttpSendRequestW(hHTTPConn,0,0,postBuffer.data(),(DWORD)postBuffer.length())) {
		bool stillError = true;
		DWORD dwError = GetLastError();	
		if (dwError == ERROR_INTERNET_INVALID_CA && settings.allowUntrustedCert) {
			DWORD dwFlags;
			DWORD dwBuffLen = sizeof(dwFlags);

			InternetQueryOption (hHTTPConn, INTERNET_OPTION_SECURITY_FLAGS,
				(LPVOID)&dwFlags, &dwBuffLen);

			dwFlags |= SECURITY_FLAG_IGNORE_UNKNOWN_CA;
			InternetSetOption (hHTTPConn, INTERNET_OPTION_SECURITY_FLAGS,
				&dwFlags, sizeof (dwFlags) );
			if (HttpSendRequestW(hHTTPConn,0,0,postBuffer.data(),(DWORD)postBuffer.length()))
				stillError = false;			
		}
		if (stillError)
			throw FileMsgException(THISLOCATION,GetLastError(),url,"Failed to SendRequest");
	}
	postBuffer.clear();
}